1 /* 2 * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #pragma ident "%Z%%M% %I% %E% SMI" 15 16 #include <sendmail.h> 17 #include <sm/sem.h> 18 19 SM_RCSID("@(#)$Id: queue.c,v 8.954 2006/04/22 01:07:00 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 bp = NULL; 3908 (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER), sizeof qf); 3909 qfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDWR_B, NULL); 3910 if (qfp == NULL) 3911 { 3912 int save_errno = errno; 3913 3914 if (tTd(40, 8)) 3915 sm_dprintf("readqf(%s): sm_io_open failure (%s)\n", 3916 qf, sm_errstring(errno)); 3917 errno = save_errno; 3918 if (errno != ENOENT 3919 ) 3920 syserr("readqf: no control file %s", qf); 3921 RELEASE_QUEUE; 3922 return false; 3923 } 3924 3925 if (!lockfile(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), qf, NULL, 3926 LOCK_EX|LOCK_NB)) 3927 { 3928 /* being processed by another queuer */ 3929 if (Verbose) 3930 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3931 "%s: locked\n", e->e_id); 3932 if (tTd(40, 8)) 3933 sm_dprintf("%s: locked\n", e->e_id); 3934 if (LogLevel > 19) 3935 sm_syslog(LOG_DEBUG, e->e_id, "locked"); 3936 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 3937 RELEASE_QUEUE; 3938 return false; 3939 } 3940 3941 RELEASE_QUEUE; 3942 3943 /* 3944 ** Prevent locking race condition. 3945 ** 3946 ** Process A: readqf(): qfp = fopen(qffile) 3947 ** Process B: queueup(): rename(tf, qf) 3948 ** Process B: unlocks(tf) 3949 ** Process A: lockfile(qf); 3950 ** 3951 ** Process A (us) has the old qf file (before the rename deleted 3952 ** the directory entry) and will be delivering based on old data. 3953 ** This can lead to multiple deliveries of the same recipients. 3954 ** 3955 ** Catch this by checking if the underlying qf file has changed 3956 ** *after* acquiring our lock and if so, act as though the file 3957 ** was still locked (i.e., just return like the lockfile() case 3958 ** above. 3959 */ 3960 3961 if (stat(qf, &stf) < 0 || 3962 fstat(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), &st) < 0) 3963 { 3964 /* must have been being processed by someone else */ 3965 if (tTd(40, 8)) 3966 sm_dprintf("readqf(%s): [f]stat failure (%s)\n", 3967 qf, sm_errstring(errno)); 3968 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 3969 return false; 3970 } 3971 3972 if (st.st_nlink != stf.st_nlink || 3973 st.st_dev != stf.st_dev || 3974 ST_INODE(st) != ST_INODE(stf) || 3975 #if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ 3976 st.st_gen != stf.st_gen || 3977 #endif /* HAS_ST_GEN && 0 */ 3978 st.st_uid != stf.st_uid || 3979 st.st_gid != stf.st_gid || 3980 st.st_size != stf.st_size) 3981 { 3982 /* changed after opened */ 3983 if (Verbose) 3984 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3985 "%s: changed\n", e->e_id); 3986 if (tTd(40, 8)) 3987 sm_dprintf("%s: changed\n", e->e_id); 3988 if (LogLevel > 19) 3989 sm_syslog(LOG_DEBUG, e->e_id, "changed"); 3990 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 3991 return false; 3992 } 3993 3994 /* 3995 ** Check the queue file for plausibility to avoid attacks. 3996 */ 3997 3998 qsafe = S_IWOTH|S_IWGRP; 3999 if (bitset(S_IWGRP, QueueFileMode)) 4000 qsafe &= ~S_IWGRP; 4001 4002 bogus = st.st_uid != geteuid() && 4003 st.st_uid != TrustedUid && 4004 geteuid() != RealUid; 4005 4006 /* 4007 ** If this qf file results from a set-group-ID binary, then 4008 ** we check whether the directory is group-writable, 4009 ** the queue file mode contains the group-writable bit, and 4010 ** the groups are the same. 4011 ** Notice: this requires that the set-group-ID binary is used to 4012 ** run the queue! 4013 */ 4014 4015 if (bogus && st.st_gid == getegid() && UseMSP) 4016 { 4017 char delim; 4018 struct stat dst; 4019 4020 bp = SM_LAST_DIR_DELIM(qf); 4021 if (bp == NULL) 4022 delim = '\0'; 4023 else 4024 { 4025 delim = *bp; 4026 *bp = '\0'; 4027 } 4028 if (stat(delim == '\0' ? "." : qf, &dst) < 0) 4029 syserr("readqf: cannot stat directory %s", 4030 delim == '\0' ? "." : qf); 4031 else 4032 { 4033 bogus = !(bitset(S_IWGRP, QueueFileMode) && 4034 bitset(S_IWGRP, dst.st_mode) && 4035 dst.st_gid == st.st_gid); 4036 } 4037 if (delim != '\0') 4038 *bp = delim; 4039 bp = NULL; 4040 } 4041 if (!bogus) 4042 bogus = bitset(qsafe, st.st_mode); 4043 if (bogus) 4044 { 4045 if (LogLevel > 0) 4046 { 4047 sm_syslog(LOG_ALERT, e->e_id, 4048 "bogus queue file, uid=%d, gid=%d, mode=%o", 4049 st.st_uid, st.st_gid, st.st_mode); 4050 } 4051 if (tTd(40, 8)) 4052 sm_dprintf("readqf(%s): bogus file\n", qf); 4053 e->e_flags |= EF_INQUEUE; 4054 if (!openonly) 4055 loseqfile(e, "bogus file uid/gid in mqueue"); 4056 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4057 return false; 4058 } 4059 4060 if (st.st_size == 0) 4061 { 4062 /* must be a bogus file -- if also old, just remove it */ 4063 if (!openonly && st.st_ctime + 10 * 60 < curtime()) 4064 { 4065 (void) xunlink(queuename(e, DATAFL_LETTER)); 4066 (void) xunlink(queuename(e, ANYQFL_LETTER)); 4067 } 4068 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4069 return false; 4070 } 4071 4072 if (st.st_nlink == 0) 4073 { 4074 /* 4075 ** Race condition -- we got a file just as it was being 4076 ** unlinked. Just assume it is zero length. 4077 */ 4078 4079 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4080 return false; 4081 } 4082 4083 #if _FFR_TRUSTED_QF 4084 /* 4085 ** If we don't own the file mark it as unsafe. 4086 ** However, allow TrustedUser to own it as well 4087 ** in case TrustedUser manipulates the queue. 4088 */ 4089 4090 if (st.st_uid != geteuid() && st.st_uid != TrustedUid) 4091 e->e_flags |= EF_UNSAFE; 4092 #else /* _FFR_TRUSTED_QF */ 4093 /* If we don't own the file mark it as unsafe */ 4094 if (st.st_uid != geteuid()) 4095 e->e_flags |= EF_UNSAFE; 4096 #endif /* _FFR_TRUSTED_QF */ 4097 4098 /* good file -- save this lock */ 4099 e->e_lockfp = qfp; 4100 4101 /* Just wanted the open file */ 4102 if (openonly) 4103 return true; 4104 4105 /* do basic system initialization */ 4106 initsys(e); 4107 macdefine(&e->e_macro, A_PERM, 'i', e->e_id); 4108 4109 LineNumber = 0; 4110 e->e_flags |= EF_GLOBALERRS; 4111 set_op_mode(MD_QUEUERUN); 4112 ctladdr = NULL; 4113 e->e_qfletter = queue_letter(e, ANYQFL_LETTER); 4114 e->e_dfqgrp = e->e_qgrp; 4115 e->e_dfqdir = e->e_qdir; 4116 #if _FFR_QUEUE_MACRO 4117 macdefine(&e->e_macro, A_TEMP, macid("{queue}"), 4118 qid_printqueue(e->e_qgrp, e->e_qdir)); 4119 #endif /* _FFR_QUEUE_MACRO */ 4120 e->e_dfino = -1; 4121 e->e_msgsize = -1; 4122 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 4123 { 4124 unsigned long qflags; 4125 ADDRESS *q; 4126 int r; 4127 time_t now; 4128 auto char *ep; 4129 4130 if (tTd(40, 4)) 4131 sm_dprintf("+++++ %s\n", bp); 4132 if (nomore) 4133 { 4134 /* hack attack */ 4135 hackattack: 4136 syserr("SECURITY ALERT: extra or bogus data in queue file: %s", 4137 bp); 4138 err = "bogus queue line"; 4139 goto fail; 4140 } 4141 switch (bp[0]) 4142 { 4143 case 'A': /* AUTH= parameter */ 4144 if (!xtextok(&bp[1])) 4145 goto hackattack; 4146 e->e_auth_param = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4147 break; 4148 4149 case 'B': /* body type */ 4150 r = check_bodytype(&bp[1]); 4151 if (!BODYTYPE_VALID(r)) 4152 goto hackattack; 4153 e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4154 break; 4155 4156 case 'C': /* specify controlling user */ 4157 ctladdr = setctluser(&bp[1], qfver, e); 4158 break; 4159 4160 case 'D': /* data file name */ 4161 /* obsolete -- ignore */ 4162 break; 4163 4164 case 'd': /* data file directory name */ 4165 { 4166 int qgrp, qdir; 4167 4168 #if _FFR_MSP_PARANOIA 4169 /* forbid queue groups in MSP? */ 4170 if (UseMSP) 4171 goto hackattack; 4172 #endif /* _FFR_MSP_PARANOIA */ 4173 for (qgrp = 0; 4174 qgrp < NumQueue && Queue[qgrp] != NULL; 4175 ++qgrp) 4176 { 4177 for (qdir = 0; 4178 qdir < Queue[qgrp]->qg_numqueues; 4179 ++qdir) 4180 { 4181 if (strcmp(&bp[1], 4182 Queue[qgrp]->qg_qpaths[qdir].qp_name) 4183 == 0) 4184 { 4185 e->e_dfqgrp = qgrp; 4186 e->e_dfqdir = qdir; 4187 goto done; 4188 } 4189 } 4190 } 4191 err = "bogus queue file directory"; 4192 goto fail; 4193 done: 4194 break; 4195 } 4196 4197 case 'E': /* specify error recipient */ 4198 /* no longer used */ 4199 break; 4200 4201 case 'F': /* flag bits */ 4202 if (strncmp(bp, "From ", 5) == 0) 4203 { 4204 /* we are being spoofed! */ 4205 syserr("SECURITY ALERT: bogus qf line %s", bp); 4206 err = "bogus queue line"; 4207 goto fail; 4208 } 4209 for (p = &bp[1]; *p != '\0'; p++) 4210 { 4211 switch (*p) 4212 { 4213 case '8': /* has 8 bit data */ 4214 e->e_flags |= EF_HAS8BIT; 4215 break; 4216 4217 case 'b': /* delete Bcc: header */ 4218 e->e_flags |= EF_DELETE_BCC; 4219 break; 4220 4221 case 'd': /* envelope has DSN RET= */ 4222 e->e_flags |= EF_RET_PARAM; 4223 break; 4224 4225 case 'n': /* don't return body */ 4226 e->e_flags |= EF_NO_BODY_RETN; 4227 break; 4228 4229 case 'r': /* response */ 4230 e->e_flags |= EF_RESPONSE; 4231 break; 4232 4233 case 's': /* split */ 4234 e->e_flags |= EF_SPLIT; 4235 break; 4236 4237 case 'w': /* warning sent */ 4238 e->e_flags |= EF_WARNING; 4239 break; 4240 } 4241 } 4242 break; 4243 4244 case 'q': /* quarantine reason */ 4245 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4246 macdefine(&e->e_macro, A_PERM, 4247 macid("{quarantine}"), e->e_quarmsg); 4248 break; 4249 4250 case 'H': /* header */ 4251 4252 /* 4253 ** count size before chompheader() destroys the line. 4254 ** this isn't accurate due to macro expansion, but 4255 ** better than before. "-3" to skip H?? at least. 4256 */ 4257 4258 hdrsize += strlen(bp) - 3; 4259 (void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e); 4260 break; 4261 4262 case 'I': /* data file's inode number */ 4263 /* regenerated below */ 4264 break; 4265 4266 case 'K': /* time of last delivery attempt */ 4267 e->e_dtime = atol(&buf[1]); 4268 break; 4269 4270 case 'L': /* Solaris Content-Length: */ 4271 case 'M': /* message */ 4272 /* ignore this; we want a new message next time */ 4273 break; 4274 4275 case 'N': /* number of delivery attempts */ 4276 e->e_ntries = atoi(&buf[1]); 4277 4278 /* if this has been tried recently, let it be */ 4279 now = curtime(); 4280 if (e->e_ntries > 0 && e->e_dtime <= now && 4281 now < e->e_dtime + MinQueueAge) 4282 { 4283 char *howlong; 4284 4285 howlong = pintvl(now - e->e_dtime, true); 4286 if (Verbose) 4287 (void) sm_io_fprintf(smioout, 4288 SM_TIME_DEFAULT, 4289 "%s: too young (%s)\n", 4290 e->e_id, howlong); 4291 if (tTd(40, 8)) 4292 sm_dprintf("%s: too young (%s)\n", 4293 e->e_id, howlong); 4294 if (LogLevel > 19) 4295 sm_syslog(LOG_DEBUG, e->e_id, 4296 "too young (%s)", 4297 howlong); 4298 e->e_id = NULL; 4299 unlockqueue(e); 4300 return false; 4301 } 4302 macdefine(&e->e_macro, A_TEMP, 4303 macid("{ntries}"), &buf[1]); 4304 4305 #if NAMED_BIND 4306 /* adjust BIND parameters immediately */ 4307 if (e->e_ntries == 0) 4308 { 4309 _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; 4310 _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; 4311 } 4312 else 4313 { 4314 _res.retry = TimeOuts.res_retry[RES_TO_NORMAL]; 4315 _res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL]; 4316 } 4317 #endif /* NAMED_BIND */ 4318 break; 4319 4320 case 'P': /* message priority */ 4321 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 4322 break; 4323 4324 case 'Q': /* original recipient */ 4325 orcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4326 break; 4327 4328 case 'r': /* final recipient */ 4329 frcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4330 break; 4331 4332 case 'R': /* specify recipient */ 4333 p = bp; 4334 qflags = 0; 4335 if (qfver >= 1) 4336 { 4337 /* get flag bits */ 4338 while (*++p != '\0' && *p != ':') 4339 { 4340 switch (*p) 4341 { 4342 case 'N': 4343 qflags |= QHASNOTIFY; 4344 break; 4345 4346 case 'S': 4347 qflags |= QPINGONSUCCESS; 4348 break; 4349 4350 case 'F': 4351 qflags |= QPINGONFAILURE; 4352 break; 4353 4354 case 'D': 4355 qflags |= QPINGONDELAY; 4356 break; 4357 4358 case 'P': 4359 qflags |= QPRIMARY; 4360 break; 4361 4362 case 'A': 4363 if (ctladdr != NULL) 4364 ctladdr->q_flags |= QALIAS; 4365 break; 4366 4367 default: /* ignore or complain? */ 4368 break; 4369 } 4370 } 4371 } 4372 else 4373 qflags |= QPRIMARY; 4374 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), 4375 "e r"); 4376 if (*p != '\0') 4377 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', 4378 NULL, e, true); 4379 else 4380 q = NULL; 4381 if (q != NULL) 4382 { 4383 /* make sure we keep the current qgrp */ 4384 if (ISVALIDQGRP(e->e_qgrp)) 4385 q->q_qgrp = e->e_qgrp; 4386 q->q_alias = ctladdr; 4387 if (qfver >= 1) 4388 q->q_flags &= ~Q_PINGFLAGS; 4389 q->q_flags |= qflags; 4390 q->q_finalrcpt = frcpt; 4391 q->q_orcpt = orcpt; 4392 (void) recipient(q, &e->e_sendqueue, 0, e); 4393 } 4394 frcpt = NULL; 4395 orcpt = NULL; 4396 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), 4397 NULL); 4398 break; 4399 4400 case 'S': /* sender */ 4401 setsender(sm_rpool_strdup_x(e->e_rpool, &bp[1]), 4402 e, NULL, '\0', true); 4403 break; 4404 4405 case 'T': /* init time */ 4406 e->e_ctime = atol(&bp[1]); 4407 break; 4408 4409 case 'V': /* queue file version number */ 4410 qfver = atoi(&bp[1]); 4411 if (qfver <= QF_VERSION) 4412 break; 4413 syserr("Version number in queue file (%d) greater than max (%d)", 4414 qfver, QF_VERSION); 4415 err = "unsupported queue file version"; 4416 goto fail; 4417 /* NOTREACHED */ 4418 break; 4419 4420 case 'Z': /* original envelope id from ESMTP */ 4421 e->e_envid = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4422 macdefine(&e->e_macro, A_PERM, 4423 macid("{dsn_envid}"), e->e_envid); 4424 break; 4425 4426 case '!': /* deliver by */ 4427 4428 /* format: flag (1 char) space long-integer */ 4429 e->e_dlvr_flag = buf[1]; 4430 e->e_deliver_by = strtol(&buf[3], NULL, 10); 4431 4432 case '$': /* define macro */ 4433 { 4434 char *p; 4435 4436 /* XXX elimate p? */ 4437 r = macid_parse(&bp[1], &ep); 4438 if (r == 0) 4439 break; 4440 p = sm_rpool_strdup_x(e->e_rpool, ep); 4441 macdefine(&e->e_macro, A_PERM, r, p); 4442 } 4443 break; 4444 4445 case '.': /* terminate file */ 4446 nomore = true; 4447 break; 4448 4449 #if _FFR_QUEUEDELAY 4450 case 'G': 4451 case 'Y': 4452 4453 /* 4454 ** Maintain backward compatibility for 4455 ** users who defined _FFR_QUEUEDELAY in 4456 ** previous releases. Remove this 4457 ** code in 8.14 or 8.15. 4458 */ 4459 4460 if (qfver == 5 || qfver == 7) 4461 break; 4462 4463 /* If not qfver 5 or 7, then 'G' or 'Y' is invalid */ 4464 /* FALLTHROUGH */ 4465 #endif /* _FFR_QUEUEDELAY */ 4466 4467 default: 4468 syserr("readqf: %s: line %d: bad line \"%s\"", 4469 qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); 4470 err = "unrecognized line"; 4471 goto fail; 4472 } 4473 4474 if (bp != buf) 4475 { 4476 sm_free(bp); /* XXX */ 4477 bp = NULL; 4478 } 4479 } 4480 4481 /* 4482 ** If we haven't read any lines, this queue file is empty. 4483 ** Arrange to remove it without referencing any null pointers. 4484 */ 4485 4486 if (LineNumber == 0) 4487 { 4488 errno = 0; 4489 e->e_flags |= EF_CLRQUEUE|EF_FATALERRS|EF_RESPONSE; 4490 return true; 4491 } 4492 4493 /* Check to make sure we have a complete queue file read */ 4494 if (!nomore) 4495 { 4496 syserr("readqf: %s: incomplete queue file read", qf); 4497 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4498 return false; 4499 } 4500 4501 /* possibly set ${dsn_ret} macro */ 4502 if (bitset(EF_RET_PARAM, e->e_flags)) 4503 { 4504 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 4505 macdefine(&e->e_macro, A_PERM, 4506 macid("{dsn_ret}"), "hdrs"); 4507 else 4508 macdefine(&e->e_macro, A_PERM, 4509 macid("{dsn_ret}"), "full"); 4510 } 4511 4512 /* 4513 ** Arrange to read the data file. 4514 */ 4515 4516 p = queuename(e, DATAFL_LETTER); 4517 e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, p, SM_IO_RDONLY_B, 4518 NULL); 4519 if (e->e_dfp == NULL) 4520 { 4521 syserr("readqf: cannot open %s", p); 4522 } 4523 else 4524 { 4525 e->e_flags |= EF_HAS_DF; 4526 if (fstat(sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD, NULL), &st) 4527 >= 0) 4528 { 4529 e->e_msgsize = st.st_size + hdrsize; 4530 e->e_dfdev = st.st_dev; 4531 e->e_dfino = ST_INODE(st); 4532 (void) sm_snprintf(buf, sizeof buf, "%ld", 4533 e->e_msgsize); 4534 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), 4535 buf); 4536 } 4537 } 4538 4539 return true; 4540 4541 fail: 4542 /* 4543 ** There was some error reading the qf file (reason is in err var.) 4544 ** Cleanup: 4545 ** close file; clear e_lockfp since it is the same as qfp, 4546 ** hence it is invalid (as file) after qfp is closed; 4547 ** the qf file is on disk, so set the flag to avoid calling 4548 ** queueup() with bogus data. 4549 */ 4550 4551 if (bp != NULL && bp != buf) 4552 { 4553 sm_free(bp); /* XXX */ 4554 bp = NULL; 4555 } 4556 if (qfp != NULL) 4557 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4558 e->e_lockfp = NULL; 4559 e->e_flags |= EF_INQUEUE; 4560 loseqfile(e, err); 4561 return false; 4562 } 4563 /* 4564 ** PRTSTR -- print a string, "unprintable" characters are shown as \oct 4565 ** 4566 ** Parameters: 4567 ** s -- string to print 4568 ** ml -- maximum length of output 4569 ** 4570 ** Returns: 4571 ** number of entries 4572 ** 4573 ** Side Effects: 4574 ** Prints a string on stdout. 4575 */ 4576 4577 static void 4578 prtstr(s, ml) 4579 char *s; 4580 int ml; 4581 { 4582 int c; 4583 4584 if (s == NULL) 4585 return; 4586 while (ml-- > 0 && ((c = *s++) != '\0')) 4587 { 4588 if (c == '\\') 4589 { 4590 if (ml-- > 0) 4591 { 4592 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 4593 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 4594 } 4595 } 4596 else if (isascii(c) && isprint(c)) 4597 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 4598 else 4599 { 4600 if ((ml -= 3) > 0) 4601 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4602 "\\%03o", c & 0xFF); 4603 } 4604 } 4605 } 4606 /* 4607 ** PRINTNQE -- print out number of entries in the mail queue 4608 ** 4609 ** Parameters: 4610 ** out -- output file pointer. 4611 ** prefix -- string to output in front of each line. 4612 ** 4613 ** Returns: 4614 ** none. 4615 */ 4616 4617 void 4618 printnqe(out, prefix) 4619 SM_FILE_T *out; 4620 char *prefix; 4621 { 4622 #if SM_CONF_SHM 4623 int i, k = 0, nrequests = 0; 4624 bool unknown = false; 4625 4626 if (ShmId == SM_SHM_NO_ID) 4627 { 4628 if (prefix == NULL) 4629 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4630 "Data unavailable: shared memory not updated\n"); 4631 else 4632 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4633 "%sNOTCONFIGURED:-1\r\n", prefix); 4634 return; 4635 } 4636 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 4637 { 4638 int j; 4639 4640 k++; 4641 for (j = 0; j < Queue[i]->qg_numqueues; j++) 4642 { 4643 int n; 4644 4645 if (StopRequest) 4646 stop_sendmail(); 4647 4648 n = QSHM_ENTRIES(Queue[i]->qg_qpaths[j].qp_idx); 4649 if (prefix != NULL) 4650 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4651 "%s%s:%d\r\n", 4652 prefix, qid_printqueue(i, j), n); 4653 else if (n < 0) 4654 { 4655 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4656 "%s: unknown number of entries\n", 4657 qid_printqueue(i, j)); 4658 unknown = true; 4659 } 4660 else if (n == 0) 4661 { 4662 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4663 "%s is empty\n", 4664 qid_printqueue(i, j)); 4665 } 4666 else if (n > 0) 4667 { 4668 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4669 "%s: entries=%d\n", 4670 qid_printqueue(i, j), n); 4671 nrequests += n; 4672 k++; 4673 } 4674 } 4675 } 4676 if (prefix == NULL && k > 1) 4677 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4678 "\t\tTotal requests: %d%s\n", 4679 nrequests, unknown ? " (about)" : ""); 4680 #else /* SM_CONF_SHM */ 4681 if (prefix == NULL) 4682 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4683 "Data unavailable without shared memory support\n"); 4684 else 4685 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4686 "%sNOTAVAILABLE:-1\r\n", prefix); 4687 #endif /* SM_CONF_SHM */ 4688 } 4689 /* 4690 ** PRINTQUEUE -- print out a representation of the mail queue 4691 ** 4692 ** Parameters: 4693 ** none. 4694 ** 4695 ** Returns: 4696 ** none. 4697 ** 4698 ** Side Effects: 4699 ** Prints a listing of the mail queue on the standard output. 4700 */ 4701 4702 void 4703 printqueue() 4704 { 4705 int i, k = 0, nrequests = 0; 4706 4707 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 4708 { 4709 int j; 4710 4711 k++; 4712 for (j = 0; j < Queue[i]->qg_numqueues; j++) 4713 { 4714 if (StopRequest) 4715 stop_sendmail(); 4716 nrequests += print_single_queue(i, j); 4717 k++; 4718 } 4719 } 4720 if (k > 1) 4721 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4722 "\t\tTotal requests: %d\n", 4723 nrequests); 4724 } 4725 /* 4726 ** PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue 4727 ** 4728 ** Parameters: 4729 ** qgrp -- the index of the queue group. 4730 ** qdir -- the queue directory. 4731 ** 4732 ** Returns: 4733 ** number of requests in mail queue. 4734 ** 4735 ** Side Effects: 4736 ** Prints a listing of the mail queue on the standard output. 4737 */ 4738 4739 int 4740 print_single_queue(qgrp, qdir) 4741 int qgrp; 4742 int qdir; 4743 { 4744 register WORK *w; 4745 SM_FILE_T *f; 4746 int nrequests; 4747 char qd[MAXPATHLEN]; 4748 char qddf[MAXPATHLEN]; 4749 char buf[MAXLINE]; 4750 4751 if (qdir == NOQDIR) 4752 { 4753 (void) sm_strlcpy(qd, ".", sizeof qd); 4754 (void) sm_strlcpy(qddf, ".", sizeof qddf); 4755 } 4756 else 4757 { 4758 (void) sm_strlcpyn(qd, sizeof qd, 2, 4759 Queue[qgrp]->qg_qpaths[qdir].qp_name, 4760 (bitset(QP_SUBQF, 4761 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs) 4762 ? "/qf" : "")); 4763 (void) sm_strlcpyn(qddf, sizeof qddf, 2, 4764 Queue[qgrp]->qg_qpaths[qdir].qp_name, 4765 (bitset(QP_SUBDF, 4766 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs) 4767 ? "/df" : "")); 4768 } 4769 4770 /* 4771 ** Check for permission to print the queue 4772 */ 4773 4774 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 4775 { 4776 struct stat st; 4777 #ifdef NGROUPS_MAX 4778 int n; 4779 extern GIDSET_T InitialGidSet[NGROUPS_MAX]; 4780 #endif /* NGROUPS_MAX */ 4781 4782 if (stat(qd, &st) < 0) 4783 { 4784 syserr("Cannot stat %s", 4785 qid_printqueue(qgrp, qdir)); 4786 return 0; 4787 } 4788 #ifdef NGROUPS_MAX 4789 n = NGROUPS_MAX; 4790 while (--n >= 0) 4791 { 4792 if (InitialGidSet[n] == st.st_gid) 4793 break; 4794 } 4795 if (n < 0 && RealGid != st.st_gid) 4796 #else /* NGROUPS_MAX */ 4797 if (RealGid != st.st_gid) 4798 #endif /* NGROUPS_MAX */ 4799 { 4800 usrerr("510 You are not permitted to see the queue"); 4801 setstat(EX_NOPERM); 4802 return 0; 4803 } 4804 } 4805 4806 /* 4807 ** Read and order the queue. 4808 */ 4809 4810 nrequests = gatherq(qgrp, qdir, true, NULL, NULL); 4811 (void) sortq(Queue[qgrp]->qg_maxlist); 4812 4813 /* 4814 ** Print the work list that we have read. 4815 */ 4816 4817 /* first see if there is anything */ 4818 if (nrequests <= 0) 4819 { 4820 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s is empty\n", 4821 qid_printqueue(qgrp, qdir)); 4822 return 0; 4823 } 4824 4825 sm_getla(); /* get load average */ 4826 4827 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\t\t%s (%d request%s", 4828 qid_printqueue(qgrp, qdir), 4829 nrequests, nrequests == 1 ? "" : "s"); 4830 if (MaxQueueRun > 0 && nrequests > MaxQueueRun) 4831 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4832 ", only %d printed", MaxQueueRun); 4833 if (Verbose) 4834 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4835 ")\n-----Q-ID----- --Size-- -Priority- ---Q-Time--- --------Sender/Recipient--------\n"); 4836 else 4837 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4838 ")\n-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------\n"); 4839 for (w = WorkQ; w != NULL; w = w->w_next) 4840 { 4841 struct stat st; 4842 auto time_t submittime = 0; 4843 long dfsize; 4844 int flags = 0; 4845 int qfver; 4846 char quarmsg[MAXLINE]; 4847 char statmsg[MAXLINE]; 4848 char bodytype[MAXNAME + 1]; 4849 char qf[MAXPATHLEN]; 4850 4851 if (StopRequest) 4852 stop_sendmail(); 4853 4854 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%13s", 4855 w->w_name + 2); 4856 (void) sm_strlcpyn(qf, sizeof qf, 3, qd, "/", w->w_name); 4857 f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDONLY_B, 4858 NULL); 4859 if (f == NULL) 4860 { 4861 if (errno == EPERM) 4862 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4863 " (permission denied)\n"); 4864 else if (errno == ENOENT) 4865 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4866 " (job completed)\n"); 4867 else 4868 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4869 " (%s)\n", 4870 sm_errstring(errno)); 4871 errno = 0; 4872 continue; 4873 } 4874 w->w_name[0] = DATAFL_LETTER; 4875 (void) sm_strlcpyn(qf, sizeof qf, 3, qddf, "/", w->w_name); 4876 if (stat(qf, &st) >= 0) 4877 dfsize = st.st_size; 4878 else 4879 { 4880 ENVELOPE e; 4881 4882 /* 4883 ** Maybe the df file can't be statted because 4884 ** it is in a different directory than the qf file. 4885 ** In order to find out, we must read the qf file. 4886 */ 4887 4888 newenvelope(&e, &BlankEnvelope, sm_rpool_new_x(NULL)); 4889 e.e_id = w->w_name + 2; 4890 e.e_qgrp = qgrp; 4891 e.e_qdir = qdir; 4892 dfsize = -1; 4893 if (readqf(&e, false)) 4894 { 4895 char *df = queuename(&e, DATAFL_LETTER); 4896 if (stat(df, &st) >= 0) 4897 dfsize = st.st_size; 4898 } 4899 if (e.e_lockfp != NULL) 4900 { 4901 (void) sm_io_close(e.e_lockfp, SM_TIME_DEFAULT); 4902 e.e_lockfp = NULL; 4903 } 4904 clearenvelope(&e, false, e.e_rpool); 4905 sm_rpool_free(e.e_rpool); 4906 } 4907 if (w->w_lock) 4908 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "*"); 4909 else if (QueueMode == QM_LOST) 4910 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "?"); 4911 else if (w->w_tooyoung) 4912 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "-"); 4913 else if (shouldqueue(w->w_pri, w->w_ctime)) 4914 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "X"); 4915 else 4916 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " "); 4917 4918 errno = 0; 4919 4920 quarmsg[0] = '\0'; 4921 statmsg[0] = bodytype[0] = '\0'; 4922 qfver = 0; 4923 while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf) != NULL) 4924 { 4925 register int i; 4926 register char *p; 4927 4928 if (StopRequest) 4929 stop_sendmail(); 4930 4931 fixcrlf(buf, true); 4932 switch (buf[0]) 4933 { 4934 case 'V': /* queue file version */ 4935 qfver = atoi(&buf[1]); 4936 break; 4937 4938 case 'M': /* error message */ 4939 if ((i = strlen(&buf[1])) >= sizeof statmsg) 4940 i = sizeof statmsg - 1; 4941 memmove(statmsg, &buf[1], i); 4942 statmsg[i] = '\0'; 4943 break; 4944 4945 case 'q': /* quarantine reason */ 4946 if ((i = strlen(&buf[1])) >= sizeof quarmsg) 4947 i = sizeof quarmsg - 1; 4948 memmove(quarmsg, &buf[1], i); 4949 quarmsg[i] = '\0'; 4950 break; 4951 4952 case 'B': /* body type */ 4953 if ((i = strlen(&buf[1])) >= sizeof bodytype) 4954 i = sizeof bodytype - 1; 4955 memmove(bodytype, &buf[1], i); 4956 bodytype[i] = '\0'; 4957 break; 4958 4959 case 'S': /* sender name */ 4960 if (Verbose) 4961 { 4962 (void) sm_io_fprintf(smioout, 4963 SM_TIME_DEFAULT, 4964 "%8ld %10ld%c%.12s ", 4965 dfsize, 4966 w->w_pri, 4967 bitset(EF_WARNING, flags) 4968 ? '+' : ' ', 4969 ctime(&submittime) + 4); 4970 prtstr(&buf[1], 78); 4971 } 4972 else 4973 { 4974 (void) sm_io_fprintf(smioout, 4975 SM_TIME_DEFAULT, 4976 "%8ld %.16s ", 4977 dfsize, 4978 ctime(&submittime)); 4979 prtstr(&buf[1], 39); 4980 } 4981 4982 if (quarmsg[0] != '\0') 4983 { 4984 (void) sm_io_fprintf(smioout, 4985 SM_TIME_DEFAULT, 4986 "\n QUARANTINE: %.*s", 4987 Verbose ? 100 : 60, 4988 quarmsg); 4989 quarmsg[0] = '\0'; 4990 } 4991 4992 if (statmsg[0] != '\0' || bodytype[0] != '\0') 4993 { 4994 (void) sm_io_fprintf(smioout, 4995 SM_TIME_DEFAULT, 4996 "\n %10.10s", 4997 bodytype); 4998 if (statmsg[0] != '\0') 4999 (void) sm_io_fprintf(smioout, 5000 SM_TIME_DEFAULT, 5001 " (%.*s)", 5002 Verbose ? 100 : 60, 5003 statmsg); 5004 statmsg[0] = '\0'; 5005 } 5006 break; 5007 5008 case 'C': /* controlling user */ 5009 if (Verbose) 5010 (void) sm_io_fprintf(smioout, 5011 SM_TIME_DEFAULT, 5012 "\n\t\t\t\t\t\t(---%.64s---)", 5013 &buf[1]); 5014 break; 5015 5016 case 'R': /* recipient name */ 5017 p = &buf[1]; 5018 if (qfver >= 1) 5019 { 5020 p = strchr(p, ':'); 5021 if (p == NULL) 5022 break; 5023 p++; 5024 } 5025 if (Verbose) 5026 { 5027 (void) sm_io_fprintf(smioout, 5028 SM_TIME_DEFAULT, 5029 "\n\t\t\t\t\t\t"); 5030 prtstr(p, 71); 5031 } 5032 else 5033 { 5034 (void) sm_io_fprintf(smioout, 5035 SM_TIME_DEFAULT, 5036 "\n\t\t\t\t\t "); 5037 prtstr(p, 38); 5038 } 5039 if (Verbose && statmsg[0] != '\0') 5040 { 5041 (void) sm_io_fprintf(smioout, 5042 SM_TIME_DEFAULT, 5043 "\n\t\t (%.100s)", 5044 statmsg); 5045 statmsg[0] = '\0'; 5046 } 5047 break; 5048 5049 case 'T': /* creation time */ 5050 submittime = atol(&buf[1]); 5051 break; 5052 5053 case 'F': /* flag bits */ 5054 for (p = &buf[1]; *p != '\0'; p++) 5055 { 5056 switch (*p) 5057 { 5058 case 'w': 5059 flags |= EF_WARNING; 5060 break; 5061 } 5062 } 5063 } 5064 } 5065 if (submittime == (time_t) 0) 5066 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 5067 " (no control file)"); 5068 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\n"); 5069 (void) sm_io_close(f, SM_TIME_DEFAULT); 5070 } 5071 return nrequests; 5072 } 5073 5074 /* 5075 ** QUEUE_LETTER -- get the proper queue letter for the current QueueMode. 5076 ** 5077 ** Parameters: 5078 ** e -- envelope to build it in/from. 5079 ** type -- the file type, used as the first character 5080 ** of the file name. 5081 ** 5082 ** Returns: 5083 ** the letter to use 5084 */ 5085 5086 static char 5087 queue_letter(e, type) 5088 ENVELOPE *e; 5089 int type; 5090 { 5091 /* Change type according to QueueMode */ 5092 if (type == ANYQFL_LETTER) 5093 { 5094 if (e->e_quarmsg != NULL) 5095 type = QUARQF_LETTER; 5096 else 5097 { 5098 switch (QueueMode) 5099 { 5100 case QM_NORMAL: 5101 type = NORMQF_LETTER; 5102 break; 5103 5104 case QM_QUARANTINE: 5105 type = QUARQF_LETTER; 5106 break; 5107 5108 case QM_LOST: 5109 type = LOSEQF_LETTER; 5110 break; 5111 5112 default: 5113 /* should never happen */ 5114 abort(); 5115 /* NOTREACHED */ 5116 } 5117 } 5118 } 5119 return type; 5120 } 5121 5122 /* 5123 ** QUEUENAME -- build a file name in the queue directory for this envelope. 5124 ** 5125 ** Parameters: 5126 ** e -- envelope to build it in/from. 5127 ** type -- the file type, used as the first character 5128 ** of the file name. 5129 ** 5130 ** Returns: 5131 ** a pointer to the queue name (in a static buffer). 5132 ** 5133 ** Side Effects: 5134 ** If no id code is already assigned, queuename() will 5135 ** assign an id code with assign_queueid(). If no queue 5136 ** directory is assigned, one will be set with setnewqueue(). 5137 */ 5138 5139 char * 5140 queuename(e, type) 5141 register ENVELOPE *e; 5142 int type; 5143 { 5144 int qd, qg; 5145 char *sub = "/"; 5146 char pref[3]; 5147 static char buf[MAXPATHLEN]; 5148 5149 /* Assign an ID if needed */ 5150 if (e->e_id == NULL) 5151 assign_queueid(e); 5152 type = queue_letter(e, type); 5153 5154 /* begin of filename */ 5155 pref[0] = (char) type; 5156 pref[1] = 'f'; 5157 pref[2] = '\0'; 5158 5159 /* Assign a queue group/directory if needed */ 5160 if (type == XSCRPT_LETTER) 5161 { 5162 /* 5163 ** We don't want to call setnewqueue() if we are fetching 5164 ** the pathname of the transcript file, because setnewqueue 5165 ** chooses a queue, and sometimes we need to write to the 5166 ** transcript file before we have gathered enough information 5167 ** to choose a queue. 5168 */ 5169 5170 if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR) 5171 { 5172 if (e->e_qgrp != NOQGRP && e->e_qdir != NOQDIR) 5173 { 5174 e->e_xfqgrp = e->e_qgrp; 5175 e->e_xfqdir = e->e_qdir; 5176 } 5177 else 5178 { 5179 e->e_xfqgrp = 0; 5180 if (Queue[e->e_xfqgrp]->qg_numqueues <= 1) 5181 e->e_xfqdir = 0; 5182 else 5183 { 5184 e->e_xfqdir = get_rand_mod( 5185 Queue[e->e_xfqgrp]->qg_numqueues); 5186 } 5187 } 5188 } 5189 qd = e->e_xfqdir; 5190 qg = e->e_xfqgrp; 5191 } 5192 else 5193 { 5194 if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR) 5195 (void) setnewqueue(e); 5196 if (type == DATAFL_LETTER) 5197 { 5198 qd = e->e_dfqdir; 5199 qg = e->e_dfqgrp; 5200 } 5201 else 5202 { 5203 qd = e->e_qdir; 5204 qg = e->e_qgrp; 5205 } 5206 } 5207 5208 /* xf files always have a valid qd and qg picked above */ 5209 if ((qd == NOQDIR || qg == NOQGRP) && type != XSCRPT_LETTER) 5210 (void) sm_strlcpyn(buf, sizeof buf, 2, pref, e->e_id); 5211 else 5212 { 5213 switch (type) 5214 { 5215 case DATAFL_LETTER: 5216 if (bitset(QP_SUBDF, Queue[qg]->qg_qpaths[qd].qp_subdirs)) 5217 sub = "/df/"; 5218 break; 5219 5220 case QUARQF_LETTER: 5221 case TEMPQF_LETTER: 5222 case NEWQFL_LETTER: 5223 case LOSEQF_LETTER: 5224 case NORMQF_LETTER: 5225 if (bitset(QP_SUBQF, Queue[qg]->qg_qpaths[qd].qp_subdirs)) 5226 sub = "/qf/"; 5227 break; 5228 5229 case XSCRPT_LETTER: 5230 if (bitset(QP_SUBXF, Queue[qg]->qg_qpaths[qd].qp_subdirs)) 5231 sub = "/xf/"; 5232 break; 5233 5234 default: 5235 sm_abort("queuename: bad queue file type %d", type); 5236 } 5237 5238 (void) sm_strlcpyn(buf, sizeof buf, 4, 5239 Queue[qg]->qg_qpaths[qd].qp_name, 5240 sub, pref, e->e_id); 5241 } 5242 5243 if (tTd(7, 2)) 5244 sm_dprintf("queuename: %s\n", buf); 5245 return buf; 5246 } 5247 5248 /* 5249 ** INIT_QID_ALG -- Initialize the (static) parameters that are used to 5250 ** generate a queue ID. 5251 ** 5252 ** This function is called by the daemon to reset 5253 ** LastQueueTime and LastQueuePid which are used by assign_queueid(). 5254 ** Otherwise the algorithm may cause problems because 5255 ** LastQueueTime and LastQueuePid are set indirectly by main() 5256 ** before the daemon process is started, hence LastQueuePid is not 5257 ** the pid of the daemon and therefore a child of the daemon can 5258 ** actually have the same pid as LastQueuePid which means the section 5259 ** in assign_queueid(): 5260 ** * see if we need to get a new base time/pid * 5261 ** is NOT triggered which will cause the same queue id to be generated. 5262 ** 5263 ** Parameters: 5264 ** none 5265 ** 5266 ** Returns: 5267 ** none. 5268 */ 5269 5270 void 5271 init_qid_alg() 5272 { 5273 LastQueueTime = 0; 5274 LastQueuePid = -1; 5275 } 5276 5277 /* 5278 ** ASSIGN_QUEUEID -- assign a queue ID for this envelope. 5279 ** 5280 ** Assigns an id code if one does not already exist. 5281 ** This code assumes that nothing will remain in the queue for 5282 ** longer than 60 years. It is critical that files with the given 5283 ** name do not already exist in the queue. 5284 ** [No longer initializes e_qdir to NOQDIR.] 5285 ** 5286 ** Parameters: 5287 ** e -- envelope to set it in. 5288 ** 5289 ** Returns: 5290 ** none. 5291 */ 5292 5293 static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 5294 # define QIC_LEN 60 5295 # define QIC_LEN_R 62 5296 5297 /* 5298 ** Note: the length is "officially" 60 because minutes and seconds are 5299 ** usually only 0-59. However (Linux): 5300 ** tm_sec The number of seconds after the minute, normally in 5301 ** the range 0 to 59, but can be up to 61 to allow for 5302 ** leap seconds. 5303 ** Hence the real length of the string is 62 to take this into account. 5304 ** Alternatively % QIC_LEN can (should) be used for access everywhere. 5305 */ 5306 5307 # define queuenextid() CurrentPid 5308 5309 5310 void 5311 assign_queueid(e) 5312 register ENVELOPE *e; 5313 { 5314 pid_t pid = queuenextid(); 5315 static int cX = 0; 5316 static long random_offset; 5317 struct tm *tm; 5318 char idbuf[MAXQFNAME - 2]; 5319 int seq; 5320 5321 if (e->e_id != NULL) 5322 return; 5323 5324 /* see if we need to get a new base time/pid */ 5325 if (cX >= QIC_LEN * QIC_LEN || LastQueueTime == 0 || 5326 LastQueuePid != pid) 5327 { 5328 time_t then = LastQueueTime; 5329 5330 /* if the first time through, pick a random offset */ 5331 if (LastQueueTime == 0) 5332 random_offset = get_random(); 5333 5334 while ((LastQueueTime = curtime()) == then && 5335 LastQueuePid == pid) 5336 { 5337 (void) sleep(1); 5338 } 5339 LastQueuePid = queuenextid(); 5340 cX = 0; 5341 } 5342 5343 /* 5344 ** Generate a new sequence number between 0 and QIC_LEN*QIC_LEN-1. 5345 ** This lets us generate up to QIC_LEN*QIC_LEN unique queue ids 5346 ** per second, per process. With envelope splitting, 5347 ** a single message can consume many queue ids. 5348 */ 5349 5350 seq = (int)((cX + random_offset) % (QIC_LEN * QIC_LEN)); 5351 ++cX; 5352 if (tTd(7, 50)) 5353 sm_dprintf("assign_queueid: random_offset = %ld (%d)\n", 5354 random_offset, seq); 5355 5356 tm = gmtime(&LastQueueTime); 5357 idbuf[0] = QueueIdChars[tm->tm_year % QIC_LEN]; 5358 idbuf[1] = QueueIdChars[tm->tm_mon]; 5359 idbuf[2] = QueueIdChars[tm->tm_mday]; 5360 idbuf[3] = QueueIdChars[tm->tm_hour]; 5361 idbuf[4] = QueueIdChars[tm->tm_min % QIC_LEN_R]; 5362 idbuf[5] = QueueIdChars[tm->tm_sec % QIC_LEN_R]; 5363 idbuf[6] = QueueIdChars[seq / QIC_LEN]; 5364 idbuf[7] = QueueIdChars[seq % QIC_LEN]; 5365 (void) sm_snprintf(&idbuf[8], sizeof idbuf - 8, "%06d", 5366 (int) LastQueuePid); 5367 e->e_id = sm_rpool_strdup_x(e->e_rpool, idbuf); 5368 macdefine(&e->e_macro, A_PERM, 'i', e->e_id); 5369 #if 0 5370 /* XXX: inherited from MainEnvelope */ 5371 e->e_qgrp = NOQGRP; /* too early to do anything else */ 5372 e->e_qdir = NOQDIR; 5373 e->e_xfqgrp = NOQGRP; 5374 #endif /* 0 */ 5375 5376 /* New ID means it's not on disk yet */ 5377 e->e_qfletter = '\0'; 5378 5379 if (tTd(7, 1)) 5380 sm_dprintf("assign_queueid: assigned id %s, e=%p\n", 5381 e->e_id, e); 5382 if (LogLevel > 93) 5383 sm_syslog(LOG_DEBUG, e->e_id, "assigned id"); 5384 } 5385 /* 5386 ** SYNC_QUEUE_TIME -- Assure exclusive PID in any given second 5387 ** 5388 ** Make sure one PID can't be used by two processes in any one second. 5389 ** 5390 ** If the system rotates PIDs fast enough, may get the 5391 ** same pid in the same second for two distinct processes. 5392 ** This will interfere with the queue file naming system. 5393 ** 5394 ** Parameters: 5395 ** none 5396 ** 5397 ** Returns: 5398 ** none 5399 */ 5400 5401 void 5402 sync_queue_time() 5403 { 5404 #if FAST_PID_RECYCLE 5405 if (OpMode != MD_TEST && 5406 OpMode != MD_VERIFY && 5407 LastQueueTime > 0 && 5408 LastQueuePid == CurrentPid && 5409 curtime() == LastQueueTime) 5410 (void) sleep(1); 5411 #endif /* FAST_PID_RECYCLE */ 5412 } 5413 /* 5414 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 5415 ** 5416 ** Parameters: 5417 ** e -- the envelope to unlock. 5418 ** 5419 ** Returns: 5420 ** none 5421 ** 5422 ** Side Effects: 5423 ** unlocks the queue for `e'. 5424 */ 5425 5426 void 5427 unlockqueue(e) 5428 ENVELOPE *e; 5429 { 5430 if (tTd(51, 4)) 5431 sm_dprintf("unlockqueue(%s)\n", 5432 e->e_id == NULL ? "NOQUEUE" : e->e_id); 5433 5434 5435 /* if there is a lock file in the envelope, close it */ 5436 if (e->e_lockfp != NULL) 5437 (void) sm_io_close(e->e_lockfp, SM_TIME_DEFAULT); 5438 e->e_lockfp = NULL; 5439 5440 /* don't create a queue id if we don't already have one */ 5441 if (e->e_id == NULL) 5442 return; 5443 5444 /* remove the transcript */ 5445 if (LogLevel > 87) 5446 sm_syslog(LOG_DEBUG, e->e_id, "unlock"); 5447 if (!tTd(51, 104)) 5448 (void) xunlink(queuename(e, XSCRPT_LETTER)); 5449 } 5450 /* 5451 ** SETCTLUSER -- create a controlling address 5452 ** 5453 ** Create a fake "address" given only a local login name; this is 5454 ** used as a "controlling user" for future recipient addresses. 5455 ** 5456 ** Parameters: 5457 ** user -- the user name of the controlling user. 5458 ** qfver -- the version stamp of this queue file. 5459 ** e -- envelope 5460 ** 5461 ** Returns: 5462 ** An address descriptor for the controlling user, 5463 ** using storage allocated from e->e_rpool. 5464 ** 5465 */ 5466 5467 static ADDRESS * 5468 setctluser(user, qfver, e) 5469 char *user; 5470 int qfver; 5471 ENVELOPE *e; 5472 { 5473 register ADDRESS *a; 5474 struct passwd *pw; 5475 char *p; 5476 5477 /* 5478 ** See if this clears our concept of controlling user. 5479 */ 5480 5481 if (user == NULL || *user == '\0') 5482 return NULL; 5483 5484 /* 5485 ** Set up addr fields for controlling user. 5486 */ 5487 5488 a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof *a); 5489 memset((char *) a, '\0', sizeof *a); 5490 5491 if (*user == ':') 5492 { 5493 p = &user[1]; 5494 a->q_user = sm_rpool_strdup_x(e->e_rpool, p); 5495 } 5496 else 5497 { 5498 p = strtok(user, ":"); 5499 a->q_user = sm_rpool_strdup_x(e->e_rpool, user); 5500 if (qfver >= 2) 5501 { 5502 if ((p = strtok(NULL, ":")) != NULL) 5503 a->q_uid = atoi(p); 5504 if ((p = strtok(NULL, ":")) != NULL) 5505 a->q_gid = atoi(p); 5506 if ((p = strtok(NULL, ":")) != NULL) 5507 { 5508 char *o; 5509 5510 a->q_flags |= QGOODUID; 5511 5512 /* if there is another ':': restore it */ 5513 if ((o = strtok(NULL, ":")) != NULL && o > p) 5514 o[-1] = ':'; 5515 } 5516 } 5517 else if ((pw = sm_getpwnam(user)) != NULL) 5518 { 5519 if (*pw->pw_dir == '\0') 5520 a->q_home = NULL; 5521 else if (strcmp(pw->pw_dir, "/") == 0) 5522 a->q_home = ""; 5523 else 5524 a->q_home = sm_rpool_strdup_x(e->e_rpool, pw->pw_dir); 5525 a->q_uid = pw->pw_uid; 5526 a->q_gid = pw->pw_gid; 5527 a->q_flags |= QGOODUID; 5528 } 5529 } 5530 5531 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 5532 a->q_mailer = LocalMailer; 5533 if (p == NULL) 5534 a->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_user); 5535 else 5536 a->q_paddr = sm_rpool_strdup_x(e->e_rpool, p); 5537 return a; 5538 } 5539 /* 5540 ** LOSEQFILE -- rename queue file with LOSEQF_LETTER & try to let someone know 5541 ** 5542 ** Parameters: 5543 ** e -- the envelope (e->e_id will be used). 5544 ** why -- reported to whomever can hear. 5545 ** 5546 ** Returns: 5547 ** none. 5548 */ 5549 5550 void 5551 loseqfile(e, why) 5552 register ENVELOPE *e; 5553 char *why; 5554 { 5555 bool loseit = true; 5556 char *p; 5557 char buf[MAXPATHLEN]; 5558 5559 if (e == NULL || e->e_id == NULL) 5560 return; 5561 p = queuename(e, ANYQFL_LETTER); 5562 if (sm_strlcpy(buf, p, sizeof buf) >= sizeof buf) 5563 return; 5564 if (!bitset(EF_INQUEUE, e->e_flags)) 5565 queueup(e, false, true); 5566 else if (QueueMode == QM_LOST) 5567 loseit = false; 5568 5569 /* if already lost, no need to re-lose */ 5570 if (loseit) 5571 { 5572 p = queuename(e, LOSEQF_LETTER); 5573 if (rename(buf, p) < 0) 5574 syserr("cannot rename(%s, %s), uid=%d", 5575 buf, p, (int) geteuid()); 5576 else if (LogLevel > 0) 5577 sm_syslog(LOG_ALERT, e->e_id, 5578 "Losing %s: %s", buf, why); 5579 } 5580 if (e->e_dfp != NULL) 5581 { 5582 (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); 5583 e->e_dfp = NULL; 5584 } 5585 e->e_flags &= ~EF_HAS_DF; 5586 } 5587 /* 5588 ** NAME2QID -- translate a queue group name to a queue group id 5589 ** 5590 ** Parameters: 5591 ** queuename -- name of queue group. 5592 ** 5593 ** Returns: 5594 ** queue group id if found. 5595 ** NOQGRP otherwise. 5596 */ 5597 5598 int 5599 name2qid(queuename) 5600 char *queuename; 5601 { 5602 register STAB *s; 5603 5604 s = stab(queuename, ST_QUEUE, ST_FIND); 5605 if (s == NULL) 5606 return NOQGRP; 5607 return s->s_quegrp->qg_index; 5608 } 5609 /* 5610 ** QID_PRINTNAME -- create externally printable version of queue id 5611 ** 5612 ** Parameters: 5613 ** e -- the envelope. 5614 ** 5615 ** Returns: 5616 ** a printable version 5617 */ 5618 5619 char * 5620 qid_printname(e) 5621 ENVELOPE *e; 5622 { 5623 char *id; 5624 static char idbuf[MAXQFNAME + 34]; 5625 5626 if (e == NULL) 5627 return ""; 5628 5629 if (e->e_id == NULL) 5630 id = ""; 5631 else 5632 id = e->e_id; 5633 5634 if (e->e_qdir == NOQDIR) 5635 return id; 5636 5637 (void) sm_snprintf(idbuf, sizeof idbuf, "%.32s/%s", 5638 Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_name, 5639 id); 5640 return idbuf; 5641 } 5642 /* 5643 ** QID_PRINTQUEUE -- create full version of queue directory for data files 5644 ** 5645 ** Parameters: 5646 ** qgrp -- index in queue group. 5647 ** qdir -- the short version of the queue directory 5648 ** 5649 ** Returns: 5650 ** the full pathname to the queue (might point to a static var) 5651 */ 5652 5653 char * 5654 qid_printqueue(qgrp, qdir) 5655 int qgrp; 5656 int qdir; 5657 { 5658 char *subdir; 5659 static char dir[MAXPATHLEN]; 5660 5661 if (qdir == NOQDIR) 5662 return Queue[qgrp]->qg_qdir; 5663 5664 if (strcmp(Queue[qgrp]->qg_qpaths[qdir].qp_name, ".") == 0) 5665 subdir = NULL; 5666 else 5667 subdir = Queue[qgrp]->qg_qpaths[qdir].qp_name; 5668 5669 (void) sm_strlcpyn(dir, sizeof dir, 4, 5670 Queue[qgrp]->qg_qdir, 5671 subdir == NULL ? "" : "/", 5672 subdir == NULL ? "" : subdir, 5673 (bitset(QP_SUBDF, 5674 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs) 5675 ? "/df" : "")); 5676 return dir; 5677 } 5678 5679 /* 5680 ** PICKQDIR -- Pick a queue directory from a queue group 5681 ** 5682 ** Parameters: 5683 ** qg -- queue group 5684 ** fsize -- file size in bytes 5685 ** e -- envelope, or NULL 5686 ** 5687 ** Result: 5688 ** NOQDIR if no queue directory in qg has enough free space to 5689 ** hold a file of size 'fsize', otherwise the index of 5690 ** a randomly selected queue directory which resides on a 5691 ** file system with enough disk space. 5692 ** XXX This could be extended to select a queuedir with 5693 ** a few (the fewest?) number of entries. That data 5694 ** is available if shared memory is used. 5695 ** 5696 ** Side Effects: 5697 ** If the request fails and e != NULL then sm_syslog is called. 5698 */ 5699 5700 int 5701 pickqdir(qg, fsize, e) 5702 QUEUEGRP *qg; 5703 long fsize; 5704 ENVELOPE *e; 5705 { 5706 int qdir; 5707 int i; 5708 long avail = 0; 5709 5710 /* Pick a random directory, as a starting point. */ 5711 if (qg->qg_numqueues <= 1) 5712 qdir = 0; 5713 else 5714 qdir = get_rand_mod(qg->qg_numqueues); 5715 5716 if (MinBlocksFree <= 0 && fsize <= 0) 5717 return qdir; 5718 5719 /* 5720 ** Now iterate over the queue directories, 5721 ** looking for a directory with enough space for this message. 5722 */ 5723 5724 i = qdir; 5725 do 5726 { 5727 QPATHS *qp = &qg->qg_qpaths[i]; 5728 long needed = 0; 5729 long fsavail = 0; 5730 5731 if (fsize > 0) 5732 needed += fsize / FILE_SYS_BLKSIZE(qp->qp_fsysidx) 5733 + ((fsize % FILE_SYS_BLKSIZE(qp->qp_fsysidx) 5734 > 0) ? 1 : 0); 5735 if (MinBlocksFree > 0) 5736 needed += MinBlocksFree; 5737 fsavail = FILE_SYS_AVAIL(qp->qp_fsysidx); 5738 #if SM_CONF_SHM 5739 if (fsavail <= 0) 5740 { 5741 long blksize; 5742 5743 /* 5744 ** might be not correctly updated, 5745 ** let's try to get the info directly. 5746 */ 5747 5748 fsavail = freediskspace(FILE_SYS_NAME(qp->qp_fsysidx), 5749 &blksize); 5750 if (fsavail < 0) 5751 fsavail = 0; 5752 } 5753 #endif /* SM_CONF_SHM */ 5754 if (needed <= fsavail) 5755 return i; 5756 if (avail < fsavail) 5757 avail = fsavail; 5758 5759 if (qg->qg_numqueues > 0) 5760 i = (i + 1) % qg->qg_numqueues; 5761 } while (i != qdir); 5762 5763 if (e != NULL && LogLevel > 0) 5764 sm_syslog(LOG_ALERT, e->e_id, 5765 "low on space (%s needs %ld bytes + %ld blocks in %s), max avail: %ld", 5766 CurHostName == NULL ? "SMTP-DAEMON" : CurHostName, 5767 fsize, MinBlocksFree, 5768 qg->qg_qdir, avail); 5769 return NOQDIR; 5770 } 5771 /* 5772 ** SETNEWQUEUE -- Sets a new queue group and directory 5773 ** 5774 ** Assign a queue group and directory to an envelope and store the 5775 ** directory in e->e_qdir. 5776 ** 5777 ** Parameters: 5778 ** e -- envelope to assign a queue for. 5779 ** 5780 ** Returns: 5781 ** true if successful 5782 ** false otherwise 5783 ** 5784 ** Side Effects: 5785 ** On success, e->e_qgrp and e->e_qdir are non-negative. 5786 ** On failure (not enough disk space), 5787 ** e->qgrp = NOQGRP, e->e_qdir = NOQDIR 5788 ** and usrerr() is invoked (which could raise an exception). 5789 */ 5790 5791 bool 5792 setnewqueue(e) 5793 ENVELOPE *e; 5794 { 5795 if (tTd(41, 20)) 5796 sm_dprintf("setnewqueue: called\n"); 5797 5798 /* not set somewhere else */ 5799 if (e->e_qgrp == NOQGRP) 5800 { 5801 ADDRESS *q; 5802 5803 /* 5804 ** Use the queue group of the "first" recipient, as set by 5805 ** the "queuegroup" rule set. If that is not defined, then 5806 ** use the queue group of the mailer of the first recipient. 5807 ** If that is not defined either, then use the default 5808 ** queue group. 5809 ** Notice: "first" depends on the sorting of sendqueue 5810 ** in recipient(). 5811 ** To avoid problems with "bad" recipients look 5812 ** for a valid address first. 5813 */ 5814 5815 q = e->e_sendqueue; 5816 while (q != NULL && 5817 (QS_IS_BADADDR(q->q_state) || QS_IS_DEAD(q->q_state))) 5818 { 5819 q = q->q_next; 5820 } 5821 if (q == NULL) 5822 e->e_qgrp = 0; 5823 else if (q->q_qgrp >= 0) 5824 e->e_qgrp = q->q_qgrp; 5825 else if (q->q_mailer != NULL && 5826 ISVALIDQGRP(q->q_mailer->m_qgrp)) 5827 e->e_qgrp = q->q_mailer->m_qgrp; 5828 else 5829 e->e_qgrp = 0; 5830 e->e_dfqgrp = e->e_qgrp; 5831 } 5832 5833 if (ISVALIDQDIR(e->e_qdir) && ISVALIDQDIR(e->e_dfqdir)) 5834 { 5835 if (tTd(41, 20)) 5836 sm_dprintf("setnewqueue: e_qdir already assigned (%s)\n", 5837 qid_printqueue(e->e_qgrp, e->e_qdir)); 5838 return true; 5839 } 5840 5841 filesys_update(); 5842 e->e_qdir = pickqdir(Queue[e->e_qgrp], e->e_msgsize, e); 5843 if (e->e_qdir == NOQDIR) 5844 { 5845 e->e_qgrp = NOQGRP; 5846 if (!bitset(EF_FATALERRS, e->e_flags)) 5847 usrerr("452 4.4.5 Insufficient disk space; try again later"); 5848 e->e_flags |= EF_FATALERRS; 5849 return false; 5850 } 5851 5852 if (tTd(41, 3)) 5853 sm_dprintf("setnewqueue: Assigned queue directory %s\n", 5854 qid_printqueue(e->e_qgrp, e->e_qdir)); 5855 5856 if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR) 5857 { 5858 e->e_xfqgrp = e->e_qgrp; 5859 e->e_xfqdir = e->e_qdir; 5860 } 5861 e->e_dfqdir = e->e_qdir; 5862 return true; 5863 } 5864 /* 5865 ** CHKQDIR -- check a queue directory 5866 ** 5867 ** Parameters: 5868 ** name -- name of queue directory 5869 ** sff -- flags for safefile() 5870 ** 5871 ** Returns: 5872 ** is it a queue directory? 5873 */ 5874 5875 static bool 5876 chkqdir(name, sff) 5877 char *name; 5878 long sff; 5879 { 5880 struct stat statb; 5881 int i; 5882 5883 /* skip over . and .. directories */ 5884 if (name[0] == '.' && 5885 (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) 5886 return false; 5887 #if HASLSTAT 5888 if (lstat(name, &statb) < 0) 5889 #else /* HASLSTAT */ 5890 if (stat(name, &statb) < 0) 5891 #endif /* HASLSTAT */ 5892 { 5893 if (tTd(41, 2)) 5894 sm_dprintf("chkqdir: stat(\"%s\"): %s\n", 5895 name, sm_errstring(errno)); 5896 return false; 5897 } 5898 #if HASLSTAT 5899 if (S_ISLNK(statb.st_mode)) 5900 { 5901 /* 5902 ** For a symlink we need to make sure the 5903 ** target is a directory 5904 */ 5905 5906 if (stat(name, &statb) < 0) 5907 { 5908 if (tTd(41, 2)) 5909 sm_dprintf("chkqdir: stat(\"%s\"): %s\n", 5910 name, sm_errstring(errno)); 5911 return false; 5912 } 5913 } 5914 #endif /* HASLSTAT */ 5915 5916 if (!S_ISDIR(statb.st_mode)) 5917 { 5918 if (tTd(41, 2)) 5919 sm_dprintf("chkqdir: \"%s\": Not a directory\n", 5920 name); 5921 return false; 5922 } 5923 5924 /* Print a warning if unsafe (but still use it) */ 5925 /* XXX do this only if we want the warning? */ 5926 i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0); 5927 if (i != 0) 5928 { 5929 if (tTd(41, 2)) 5930 sm_dprintf("chkqdir: \"%s\": Not safe: %s\n", 5931 name, sm_errstring(i)); 5932 #if _FFR_CHK_QUEUE 5933 if (LogLevel > 8) 5934 sm_syslog(LOG_WARNING, NOQID, 5935 "queue directory \"%s\": Not safe: %s", 5936 name, sm_errstring(i)); 5937 #endif /* _FFR_CHK_QUEUE */ 5938 } 5939 return true; 5940 } 5941 /* 5942 ** MULTIQUEUE_CACHE -- cache a list of paths to queues. 5943 ** 5944 ** Each potential queue is checked as the cache is built. 5945 ** Thereafter, each is blindly trusted. 5946 ** Note that we can be called again after a timeout to rebuild 5947 ** (although code for that is not ready yet). 5948 ** 5949 ** Parameters: 5950 ** basedir -- base of all queue directories. 5951 ** blen -- strlen(basedir). 5952 ** qg -- queue group. 5953 ** qn -- number of queue directories already cached. 5954 ** phash -- pointer to hash value over queue dirs. 5955 #if SM_CONF_SHM 5956 ** only used if shared memory is active. 5957 #endif * SM_CONF_SHM * 5958 ** 5959 ** Returns: 5960 ** new number of queue directories. 5961 */ 5962 5963 #define INITIAL_SLOTS 20 5964 #define ADD_SLOTS 10 5965 5966 static int 5967 multiqueue_cache(basedir, blen, qg, qn, phash) 5968 char *basedir; 5969 int blen; 5970 QUEUEGRP *qg; 5971 int qn; 5972 unsigned int *phash; 5973 { 5974 char *cp; 5975 int i, len; 5976 int slotsleft = 0; 5977 long sff = SFF_ANYFILE; 5978 char qpath[MAXPATHLEN]; 5979 char subdir[MAXPATHLEN]; 5980 char prefix[MAXPATHLEN]; /* dir relative to basedir */ 5981 5982 if (tTd(41, 20)) 5983 sm_dprintf("multiqueue_cache: called\n"); 5984 5985 /* Initialize to current directory */ 5986 prefix[0] = '.'; 5987 prefix[1] = '\0'; 5988 if (qg->qg_numqueues != 0 && qg->qg_qpaths != NULL) 5989 { 5990 for (i = 0; i < qg->qg_numqueues; i++) 5991 { 5992 if (qg->qg_qpaths[i].qp_name != NULL) 5993 (void) sm_free(qg->qg_qpaths[i].qp_name); /* XXX */ 5994 } 5995 (void) sm_free((char *) qg->qg_qpaths); /* XXX */ 5996 qg->qg_qpaths = NULL; 5997 qg->qg_numqueues = 0; 5998 } 5999 6000 /* If running as root, allow safedirpath() checks to use privs */ 6001 if (RunAsUid == 0) 6002 sff |= SFF_ROOTOK; 6003 #if _FFR_CHK_QUEUE 6004 sff |= SFF_SAFEDIRPATH|SFF_NOWWFILES; 6005 if (!UseMSP) 6006 sff |= SFF_NOGWFILES; 6007 #endif /* _FFR_CHK_QUEUE */ 6008 6009 if (!SM_IS_DIR_START(qg->qg_qdir)) 6010 { 6011 /* 6012 ** XXX we could add basedir, but then we have to realloc() 6013 ** the string... Maybe another time. 6014 */ 6015 6016 syserr("QueuePath %s not absolute", qg->qg_qdir); 6017 ExitStat = EX_CONFIG; 6018 return qn; 6019 } 6020 6021 /* qpath: directory of current workgroup */ 6022 len = sm_strlcpy(qpath, qg->qg_qdir, sizeof qpath); 6023 if (len >= sizeof qpath) 6024 { 6025 syserr("QueuePath %.256s too long (%d max)", 6026 qg->qg_qdir, (int) sizeof qpath); 6027 ExitStat = EX_CONFIG; 6028 return qn; 6029 } 6030 6031 /* begin of qpath must be same as basedir */ 6032 if (strncmp(basedir, qpath, blen) != 0 && 6033 (strncmp(basedir, qpath, blen - 1) != 0 || len != blen - 1)) 6034 { 6035 syserr("QueuePath %s not subpath of QueueDirectory %s", 6036 qpath, basedir); 6037 ExitStat = EX_CONFIG; 6038 return qn; 6039 } 6040 6041 /* Do we have a nested subdirectory? */ 6042 if (blen < len && SM_FIRST_DIR_DELIM(qg->qg_qdir + blen) != NULL) 6043 { 6044 6045 /* Copy subdirectory into prefix for later use */ 6046 if (sm_strlcpy(prefix, qg->qg_qdir + blen, sizeof prefix) >= 6047 sizeof prefix) 6048 { 6049 syserr("QueuePath %.256s too long (%d max)", 6050 qg->qg_qdir, (int) sizeof qpath); 6051 ExitStat = EX_CONFIG; 6052 return qn; 6053 } 6054 cp = SM_LAST_DIR_DELIM(prefix); 6055 SM_ASSERT(cp != NULL); 6056 *cp = '\0'; /* cut off trailing / */ 6057 } 6058 6059 /* This is guaranteed by the basedir check above */ 6060 SM_ASSERT(len >= blen - 1); 6061 cp = &qpath[len - 1]; 6062 if (*cp == '*') 6063 { 6064 register DIR *dp; 6065 register struct dirent *d; 6066 int off; 6067 char *delim; 6068 char relpath[MAXPATHLEN]; 6069 6070 *cp = '\0'; /* Overwrite wildcard */ 6071 if ((cp = SM_LAST_DIR_DELIM(qpath)) == NULL) 6072 { 6073 syserr("QueueDirectory: can not wildcard relative path"); 6074 if (tTd(41, 2)) 6075 sm_dprintf("multiqueue_cache: \"%s*\": Can not wildcard relative path.\n", 6076 qpath); 6077 ExitStat = EX_CONFIG; 6078 return qn; 6079 } 6080 if (cp == qpath) 6081 { 6082 /* 6083 ** Special case of top level wildcard, like /foo* 6084 ** Change to //foo* 6085 */ 6086 6087 (void) sm_strlcpy(qpath + 1, qpath, sizeof qpath - 1); 6088 ++cp; 6089 } 6090 delim = cp; 6091 *(cp++) = '\0'; /* Replace / with \0 */ 6092 len = strlen(cp); /* Last component of queue directory */ 6093 6094 /* 6095 ** Path relative to basedir, with trailing / 6096 ** It will be modified below to specify the subdirectories 6097 ** so they can be opened without chdir(). 6098 */ 6099 6100 off = sm_strlcpyn(relpath, sizeof relpath, 2, prefix, "/"); 6101 SM_ASSERT(off < sizeof relpath); 6102 6103 if (tTd(41, 2)) 6104 sm_dprintf("multiqueue_cache: prefix=\"%s%s\"\n", 6105 relpath, cp); 6106 6107 /* It is always basedir: we don't need to store it per group */ 6108 /* XXX: optimize this! -> one more global? */ 6109 qg->qg_qdir = newstr(basedir); 6110 qg->qg_qdir[blen - 1] = '\0'; /* cut off trailing / */ 6111 6112 /* 6113 ** XXX Should probably wrap this whole loop in a timeout 6114 ** in case some wag decides to NFS mount the queues. 6115 */ 6116 6117 /* Test path to get warning messages. */ 6118 if (qn == 0) 6119 { 6120 /* XXX qg_runasuid and qg_runasgid for specials? */ 6121 i = safedirpath(basedir, RunAsUid, RunAsGid, NULL, 6122 sff, 0, 0); 6123 if (i != 0 && tTd(41, 2)) 6124 sm_dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", 6125 basedir, sm_errstring(i)); 6126 } 6127 6128 if ((dp = opendir(prefix)) == NULL) 6129 { 6130 syserr("can not opendir(%s/%s)", qg->qg_qdir, prefix); 6131 if (tTd(41, 2)) 6132 sm_dprintf("multiqueue_cache: opendir(\"%s/%s\"): %s\n", 6133 qg->qg_qdir, prefix, 6134 sm_errstring(errno)); 6135 ExitStat = EX_CONFIG; 6136 return qn; 6137 } 6138 while ((d = readdir(dp)) != NULL) 6139 { 6140 i = strlen(d->d_name); 6141 if (i < len || strncmp(d->d_name, cp, len) != 0) 6142 { 6143 if (tTd(41, 5)) 6144 sm_dprintf("multiqueue_cache: \"%s\", skipped\n", 6145 d->d_name); 6146 continue; 6147 } 6148 6149 /* Create relative pathname: prefix + local directory */ 6150 i = sizeof(relpath) - off; 6151 if (sm_strlcpy(relpath + off, d->d_name, i) >= i) 6152 continue; /* way too long */ 6153 6154 if (!chkqdir(relpath, sff)) 6155 continue; 6156 6157 if (qg->qg_qpaths == NULL) 6158 { 6159 slotsleft = INITIAL_SLOTS; 6160 qg->qg_qpaths = (QPATHS *)xalloc((sizeof *qg->qg_qpaths) * 6161 slotsleft); 6162 qg->qg_numqueues = 0; 6163 } 6164 else if (slotsleft < 1) 6165 { 6166 qg->qg_qpaths = (QPATHS *)sm_realloc((char *)qg->qg_qpaths, 6167 (sizeof *qg->qg_qpaths) * 6168 (qg->qg_numqueues + 6169 ADD_SLOTS)); 6170 if (qg->qg_qpaths == NULL) 6171 { 6172 (void) closedir(dp); 6173 return qn; 6174 } 6175 slotsleft += ADD_SLOTS; 6176 } 6177 6178 /* check subdirs */ 6179 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs = QP_NOSUB; 6180 6181 #define CHKRSUBDIR(name, flag) \ 6182 (void) sm_strlcpyn(subdir, sizeof subdir, 3, relpath, "/", name); \ 6183 if (chkqdir(subdir, sff)) \ 6184 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs |= flag; \ 6185 else 6186 6187 6188 CHKRSUBDIR("qf", QP_SUBQF); 6189 CHKRSUBDIR("df", QP_SUBDF); 6190 CHKRSUBDIR("xf", QP_SUBXF); 6191 6192 /* assert(strlen(d->d_name) < MAXPATHLEN - 14) */ 6193 /* maybe even - 17 (subdirs) */ 6194 6195 if (prefix[0] != '.') 6196 qg->qg_qpaths[qg->qg_numqueues].qp_name = 6197 newstr(relpath); 6198 else 6199 qg->qg_qpaths[qg->qg_numqueues].qp_name = 6200 newstr(d->d_name); 6201 6202 if (tTd(41, 2)) 6203 sm_dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n", 6204 qg->qg_numqueues, relpath, 6205 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs); 6206 #if SM_CONF_SHM 6207 qg->qg_qpaths[qg->qg_numqueues].qp_idx = qn; 6208 *phash = hash_q(relpath, *phash); 6209 #endif /* SM_CONF_SHM */ 6210 qg->qg_numqueues++; 6211 ++qn; 6212 slotsleft--; 6213 } 6214 (void) closedir(dp); 6215 6216 /* undo damage */ 6217 *delim = '/'; 6218 } 6219 if (qg->qg_numqueues == 0) 6220 { 6221 qg->qg_qpaths = (QPATHS *) xalloc(sizeof *qg->qg_qpaths); 6222 6223 /* test path to get warning messages */ 6224 i = safedirpath(qpath, RunAsUid, RunAsGid, NULL, sff, 0, 0); 6225 if (i == ENOENT) 6226 { 6227 syserr("can not opendir(%s)", qpath); 6228 if (tTd(41, 2)) 6229 sm_dprintf("multiqueue_cache: opendir(\"%s\"): %s\n", 6230 qpath, sm_errstring(i)); 6231 ExitStat = EX_CONFIG; 6232 return qn; 6233 } 6234 6235 qg->qg_qpaths[0].qp_subdirs = QP_NOSUB; 6236 qg->qg_numqueues = 1; 6237 6238 /* check subdirs */ 6239 #define CHKSUBDIR(name, flag) \ 6240 (void) sm_strlcpyn(subdir, sizeof subdir, 3, qg->qg_qdir, "/", name); \ 6241 if (chkqdir(subdir, sff)) \ 6242 qg->qg_qpaths[0].qp_subdirs |= flag; \ 6243 else 6244 6245 CHKSUBDIR("qf", QP_SUBQF); 6246 CHKSUBDIR("df", QP_SUBDF); 6247 CHKSUBDIR("xf", QP_SUBXF); 6248 6249 if (qg->qg_qdir[blen - 1] != '\0' && 6250 qg->qg_qdir[blen] != '\0') 6251 { 6252 /* 6253 ** Copy the last component into qpaths and 6254 ** cut off qdir 6255 */ 6256 6257 qg->qg_qpaths[0].qp_name = newstr(qg->qg_qdir + blen); 6258 qg->qg_qdir[blen - 1] = '\0'; 6259 } 6260 else 6261 qg->qg_qpaths[0].qp_name = newstr("."); 6262 6263 #if SM_CONF_SHM 6264 qg->qg_qpaths[0].qp_idx = qn; 6265 *phash = hash_q(qg->qg_qpaths[0].qp_name, *phash); 6266 #endif /* SM_CONF_SHM */ 6267 ++qn; 6268 } 6269 return qn; 6270 } 6271 6272 /* 6273 ** FILESYS_FIND -- find entry in FileSys table, or add new one 6274 ** 6275 ** Given the pathname of a directory, determine the file system 6276 ** in which that directory resides, and return a pointer to the 6277 ** entry in the FileSys table that describes the file system. 6278 ** A new entry is added if necessary (and requested). 6279 ** If the directory does not exist, -1 is returned. 6280 ** 6281 ** Parameters: 6282 ** name -- name of directory (must be persistent!) 6283 ** path -- pathname of directory (name plus maybe "/df") 6284 ** add -- add to structure if not found. 6285 ** 6286 ** Returns: 6287 ** >=0: found: index in file system table 6288 ** <0: some error, i.e., 6289 ** FSF_TOO_MANY: too many filesystems (-> syserr()) 6290 ** FSF_STAT_FAIL: can't stat() filesystem (-> syserr()) 6291 ** FSF_NOT_FOUND: not in list 6292 */ 6293 6294 static short filesys_find __P((char *, char *, bool)); 6295 6296 #define FSF_NOT_FOUND (-1) 6297 #define FSF_STAT_FAIL (-2) 6298 #define FSF_TOO_MANY (-3) 6299 6300 static short 6301 filesys_find(name, path, add) 6302 char *name; 6303 char *path; 6304 bool add; 6305 { 6306 struct stat st; 6307 short i; 6308 6309 if (stat(path, &st) < 0) 6310 { 6311 syserr("cannot stat queue directory %s", path); 6312 return FSF_STAT_FAIL; 6313 } 6314 for (i = 0; i < NumFileSys; ++i) 6315 { 6316 if (FILE_SYS_DEV(i) == st.st_dev) 6317 return i; 6318 } 6319 if (i >= MAXFILESYS) 6320 { 6321 syserr("too many queue file systems (%d max)", MAXFILESYS); 6322 return FSF_TOO_MANY; 6323 } 6324 if (!add) 6325 return FSF_NOT_FOUND; 6326 6327 ++NumFileSys; 6328 FILE_SYS_NAME(i) = name; 6329 FILE_SYS_DEV(i) = st.st_dev; 6330 FILE_SYS_AVAIL(i) = 0; 6331 FILE_SYS_BLKSIZE(i) = 1024; /* avoid divide by zero */ 6332 return i; 6333 } 6334 6335 /* 6336 ** FILESYS_SETUP -- set up mapping from queue directories to file systems 6337 ** 6338 ** This data structure is used to efficiently check the amount of 6339 ** free space available in a set of queue directories. 6340 ** 6341 ** Parameters: 6342 ** add -- initialize structure if necessary. 6343 ** 6344 ** Returns: 6345 ** 0: success 6346 ** <0: some error, i.e., 6347 ** FSF_NOT_FOUND: not in list 6348 ** FSF_STAT_FAIL: can't stat() filesystem (-> syserr()) 6349 ** FSF_TOO_MANY: too many filesystems (-> syserr()) 6350 */ 6351 6352 static int filesys_setup __P((bool)); 6353 6354 static int 6355 filesys_setup(add) 6356 bool add; 6357 { 6358 int i, j; 6359 short fs; 6360 int ret; 6361 6362 ret = 0; 6363 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 6364 { 6365 for (j = 0; j < Queue[i]->qg_numqueues; ++j) 6366 { 6367 QPATHS *qp = &Queue[i]->qg_qpaths[j]; 6368 char qddf[MAXPATHLEN]; 6369 6370 (void) sm_strlcpyn(qddf, sizeof qddf, 2, qp->qp_name, 6371 (bitset(QP_SUBDF, qp->qp_subdirs) 6372 ? "/df" : "")); 6373 fs = filesys_find(qp->qp_name, qddf, add); 6374 if (fs >= 0) 6375 qp->qp_fsysidx = fs; 6376 else 6377 qp->qp_fsysidx = 0; 6378 if (fs < ret) 6379 ret = fs; 6380 } 6381 } 6382 return ret; 6383 } 6384 6385 /* 6386 ** FILESYS_UPDATE -- update amount of free space on all file systems 6387 ** 6388 ** The FileSys table is used to cache the amount of free space 6389 ** available on all queue directory file systems. 6390 ** This function updates the cached information if it has expired. 6391 ** 6392 ** Parameters: 6393 ** none. 6394 ** 6395 ** Returns: 6396 ** none. 6397 ** 6398 ** Side Effects: 6399 ** Updates FileSys table. 6400 */ 6401 6402 void 6403 filesys_update() 6404 { 6405 int i; 6406 long avail, blksize; 6407 time_t now; 6408 static time_t nextupdate = 0; 6409 6410 #if SM_CONF_SHM 6411 /* only the daemon updates this structure */ 6412 if (ShmId == SM_SHM_NO_ID || DaemonPid != CurrentPid) 6413 return; 6414 #endif /* SM_CONF_SHM */ 6415 now = curtime(); 6416 if (now < nextupdate) 6417 return; 6418 nextupdate = now + FILESYS_UPDATE_INTERVAL; 6419 for (i = 0; i < NumFileSys; ++i) 6420 { 6421 FILESYS *fs = &FILE_SYS(i); 6422 6423 avail = freediskspace(FILE_SYS_NAME(i), &blksize); 6424 if (avail < 0 || blksize <= 0) 6425 { 6426 if (LogLevel > 5) 6427 sm_syslog(LOG_ERR, NOQID, 6428 "filesys_update failed: %s, fs=%s, avail=%ld, blocksize=%ld", 6429 sm_errstring(errno), 6430 FILE_SYS_NAME(i), avail, blksize); 6431 fs->fs_avail = 0; 6432 fs->fs_blksize = 1024; /* avoid divide by zero */ 6433 nextupdate = now + 2; /* let's do this soon again */ 6434 } 6435 else 6436 { 6437 fs->fs_avail = avail; 6438 fs->fs_blksize = blksize; 6439 } 6440 } 6441 } 6442 6443 #if _FFR_ANY_FREE_FS 6444 /* 6445 ** FILESYS_FREE -- check whether there is at least one fs with enough space. 6446 ** 6447 ** Parameters: 6448 ** fsize -- file size in bytes 6449 ** 6450 ** Returns: 6451 ** true iff there is one fs with more than fsize bytes free. 6452 */ 6453 6454 bool 6455 filesys_free(fsize) 6456 long fsize; 6457 { 6458 int i; 6459 6460 if (fsize <= 0) 6461 return true; 6462 for (i = 0; i < NumFileSys; ++i) 6463 { 6464 long needed = 0; 6465 6466 if (FILE_SYS_AVAIL(i) < 0 || FILE_SYS_BLKSIZE(i) <= 0) 6467 continue; 6468 needed += fsize / FILE_SYS_BLKSIZE(i) 6469 + ((fsize % FILE_SYS_BLKSIZE(i) 6470 > 0) ? 1 : 0) 6471 + MinBlocksFree; 6472 if (needed <= FILE_SYS_AVAIL(i)) 6473 return true; 6474 } 6475 return false; 6476 } 6477 #endif /* _FFR_ANY_FREE_FS */ 6478 6479 #if _FFR_CONTROL_MSTAT 6480 /* 6481 ** DISK_STATUS -- show amount of free space in queue directories 6482 ** 6483 ** Parameters: 6484 ** out -- output file pointer. 6485 ** prefix -- string to output in front of each line. 6486 ** 6487 ** Returns: 6488 ** none. 6489 */ 6490 6491 void 6492 disk_status(out, prefix) 6493 SM_FILE_T *out; 6494 char *prefix; 6495 { 6496 int i; 6497 long avail, blksize; 6498 long free; 6499 6500 for (i = 0; i < NumFileSys; ++i) 6501 { 6502 avail = freediskspace(FILE_SYS_NAME(i), &blksize); 6503 if (avail >= 0 && blksize > 0) 6504 { 6505 free = (long)((double) avail * 6506 ((double) blksize / 1024)); 6507 } 6508 else 6509 free = -1; 6510 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 6511 "%s%d/%s/%ld\r\n", 6512 prefix, i, 6513 FILE_SYS_NAME(i), 6514 free); 6515 } 6516 } 6517 #endif /* _FFR_CONTROL_MSTAT */ 6518 6519 #if SM_CONF_SHM 6520 6521 /* 6522 ** INIT_SEM -- initialize semaphore system 6523 ** 6524 ** Parameters: 6525 ** owner -- is this the owner of semaphores? 6526 ** 6527 ** Returns: 6528 ** none. 6529 */ 6530 6531 #if _FFR_USE_SEM_LOCKING 6532 #if SM_CONF_SEM 6533 static int SemId = -1; /* Semaphore Id */ 6534 int SemKey = SM_SEM_KEY; 6535 #endif /* SM_CONF_SEM */ 6536 #endif /* _FFR_USE_SEM_LOCKING */ 6537 6538 static void init_sem __P((bool)); 6539 6540 static void 6541 init_sem(owner) 6542 bool owner; 6543 { 6544 #if _FFR_USE_SEM_LOCKING 6545 #if SM_CONF_SEM 6546 SemId = sm_sem_start(SemKey, 1, 0, owner); 6547 if (SemId < 0) 6548 { 6549 sm_syslog(LOG_ERR, NOQID, 6550 "func=init_sem, sem_key=%ld, sm_sem_start=%d", 6551 (long) SemKey, SemId); 6552 return; 6553 } 6554 #endif /* SM_CONF_SEM */ 6555 #endif /* _FFR_USE_SEM_LOCKING */ 6556 return; 6557 } 6558 6559 /* 6560 ** STOP_SEM -- stop semaphore system 6561 ** 6562 ** Parameters: 6563 ** owner -- is this the owner of semaphores? 6564 ** 6565 ** Returns: 6566 ** none. 6567 */ 6568 6569 static void stop_sem __P((bool)); 6570 6571 static void 6572 stop_sem(owner) 6573 bool owner; 6574 { 6575 #if _FFR_USE_SEM_LOCKING 6576 #if SM_CONF_SEM 6577 if (owner && SemId >= 0) 6578 sm_sem_stop(SemId); 6579 #endif /* SM_CONF_SEM */ 6580 #endif /* _FFR_USE_SEM_LOCKING */ 6581 return; 6582 } 6583 6584 /* 6585 ** UPD_QS -- update information about queue when adding/deleting an entry 6586 ** 6587 ** Parameters: 6588 ** e -- envelope. 6589 ** count -- add/remove entry (+1/0/-1: add/no change/remove) 6590 ** space -- update the space available as well. 6591 ** (>0/0/<0: add/no change/remove) 6592 ** where -- caller (for logging) 6593 ** 6594 ** Returns: 6595 ** none. 6596 ** 6597 ** Side Effects: 6598 ** Modifies available space in filesystem. 6599 ** Changes number of entries in queue directory. 6600 */ 6601 6602 void 6603 upd_qs(e, count, space, where) 6604 ENVELOPE *e; 6605 int count; 6606 int space; 6607 char *where; 6608 { 6609 short fidx; 6610 int idx; 6611 # if _FFR_USE_SEM_LOCKING 6612 int r; 6613 # endif /* _FFR_USE_SEM_LOCKING */ 6614 long s; 6615 6616 if (ShmId == SM_SHM_NO_ID || e == NULL) 6617 return; 6618 if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR) 6619 return; 6620 idx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_idx; 6621 if (tTd(73,2)) 6622 sm_dprintf("func=upd_qs, count=%d, space=%d, where=%s, idx=%d, entries=%d\n", 6623 count, space, where, idx, QSHM_ENTRIES(idx)); 6624 6625 /* XXX in theory this needs to be protected with a mutex */ 6626 if (QSHM_ENTRIES(idx) >= 0 && count != 0) 6627 { 6628 # if _FFR_USE_SEM_LOCKING 6629 r = sm_sem_acq(SemId, 0, 1); 6630 # endif /* _FFR_USE_SEM_LOCKING */ 6631 QSHM_ENTRIES(idx) += count; 6632 # if _FFR_USE_SEM_LOCKING 6633 if (r >= 0) 6634 r = sm_sem_rel(SemId, 0, 1); 6635 # endif /* _FFR_USE_SEM_LOCKING */ 6636 } 6637 6638 fidx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_fsysidx; 6639 if (fidx < 0) 6640 return; 6641 6642 /* update available space also? (might be loseqfile) */ 6643 if (space == 0) 6644 return; 6645 6646 /* convert size to blocks; this causes rounding errors */ 6647 s = e->e_msgsize / FILE_SYS_BLKSIZE(fidx); 6648 if (s == 0) 6649 return; 6650 6651 /* XXX in theory this needs to be protected with a mutex */ 6652 if (space > 0) 6653 FILE_SYS_AVAIL(fidx) += s; 6654 else 6655 FILE_SYS_AVAIL(fidx) -= s; 6656 6657 } 6658 6659 #if _FFR_SELECT_SHM 6660 6661 static bool write_key_file __P((char *, long)); 6662 static long read_key_file __P((char *, long)); 6663 6664 /* 6665 ** WRITE_KEY_FILE -- record some key into a file. 6666 ** 6667 ** Parameters: 6668 ** keypath -- file name. 6669 ** key -- key to write. 6670 ** 6671 ** Returns: 6672 ** true iff file could be written. 6673 ** 6674 ** Side Effects: 6675 ** writes file. 6676 */ 6677 6678 static bool 6679 write_key_file(keypath, key) 6680 char *keypath; 6681 long key; 6682 { 6683 bool ok; 6684 long sff; 6685 SM_FILE_T *keyf; 6686 6687 ok = false; 6688 if (keypath == NULL || *keypath == '\0') 6689 return ok; 6690 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; 6691 if (TrustedUid != 0 && RealUid == TrustedUid) 6692 sff |= SFF_OPENASROOT; 6693 keyf = safefopen(keypath, O_WRONLY|O_TRUNC, FileMode, sff); 6694 if (keyf == NULL) 6695 { 6696 sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s", 6697 keypath, sm_errstring(errno)); 6698 } 6699 else 6700 { 6701 if (geteuid() == 0 && RunAsUid != 0) 6702 { 6703 # if HASFCHOWN 6704 int fd; 6705 6706 fd = keyf->f_file; 6707 if (fd >= 0 && fchown(fd, RunAsUid, -1) < 0) 6708 { 6709 int err = errno; 6710 6711 sm_syslog(LOG_ALERT, NOQID, 6712 "ownership change on %s to %d failed: %s", 6713 keypath, RunAsUid, sm_errstring(err)); 6714 } 6715 # endif /* HASFCHOWN */ 6716 } 6717 ok = sm_io_fprintf(keyf, SM_TIME_DEFAULT, "%ld\n", key) != 6718 SM_IO_EOF; 6719 ok = (sm_io_close(keyf, SM_TIME_DEFAULT) != SM_IO_EOF) && ok; 6720 } 6721 return ok; 6722 } 6723 6724 /* 6725 ** READ_KEY_FILE -- read a key from a file. 6726 ** 6727 ** Parameters: 6728 ** keypath -- file name. 6729 ** key -- default key. 6730 ** 6731 ** Returns: 6732 ** key. 6733 */ 6734 6735 static long 6736 read_key_file(keypath, key) 6737 char *keypath; 6738 long key; 6739 { 6740 int r; 6741 long sff, n; 6742 SM_FILE_T *keyf; 6743 6744 if (keypath == NULL || *keypath == '\0') 6745 return key; 6746 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY; 6747 if (RealUid == 0 || (TrustedUid != 0 && RealUid == TrustedUid)) 6748 sff |= SFF_OPENASROOT; 6749 keyf = safefopen(keypath, O_RDONLY, FileMode, sff); 6750 if (keyf == NULL) 6751 { 6752 sm_syslog(LOG_ERR, NOQID, "unable to read %s: %s", 6753 keypath, sm_errstring(errno)); 6754 } 6755 else 6756 { 6757 r = sm_io_fscanf(keyf, SM_TIME_DEFAULT, "%ld", &n); 6758 if (r == 1) 6759 key = n; 6760 (void) sm_io_close(keyf, SM_TIME_DEFAULT); 6761 } 6762 return key; 6763 } 6764 #endif /* _FFR_SELECT_SHM */ 6765 6766 /* 6767 ** INIT_SHM -- initialize shared memory structure 6768 ** 6769 ** Initialize or attach to shared memory segment. 6770 ** Currently it is not a fatal error if this doesn't work. 6771 ** However, it causes us to have a "fallback" storage location 6772 ** for everything that is supposed to be in the shared memory, 6773 ** which makes the code slightly ugly. 6774 ** 6775 ** Parameters: 6776 ** qn -- number of queue directories. 6777 ** owner -- owner of shared memory. 6778 ** hash -- identifies data that is stored in shared memory. 6779 ** 6780 ** Returns: 6781 ** none. 6782 */ 6783 6784 static void init_shm __P((int, bool, unsigned int)); 6785 6786 static void 6787 init_shm(qn, owner, hash) 6788 int qn; 6789 bool owner; 6790 unsigned int hash; 6791 { 6792 int i; 6793 int count; 6794 int save_errno; 6795 #if _FFR_SELECT_SHM 6796 bool keyselect; 6797 #endif /* _FFR_SELECT_SHM */ 6798 6799 PtrFileSys = &FileSys[0]; 6800 PNumFileSys = &Numfilesys; 6801 #if _FFR_SELECT_SHM 6802 /* if this "key" is specified: select one yourself */ 6803 # define SEL_SHM_KEY ((key_t) -1) 6804 # define FIRST_SHM_KEY 25 6805 #endif /* _FFR_SELECT_SHM */ 6806 6807 /* This allows us to disable shared memory at runtime. */ 6808 if (ShmKey == 0) 6809 return; 6810 6811 count = 0; 6812 shms = SM_T_SIZE + qn * sizeof(QUEUE_SHM_T); 6813 #if _FFR_SELECT_SHM 6814 keyselect = ShmKey == SEL_SHM_KEY; 6815 if (keyselect) 6816 { 6817 if (owner) 6818 ShmKey = FIRST_SHM_KEY; 6819 else 6820 { 6821 ShmKey = read_key_file(ShmKeyFile, ShmKey); 6822 keyselect = false; 6823 if (ShmKey == SEL_SHM_KEY) 6824 goto error; 6825 } 6826 } 6827 #endif /* _FFR_SELECT_SHM */ 6828 for (;;) 6829 { 6830 /* allow read/write access for group? */ 6831 Pshm = sm_shmstart(ShmKey, shms, 6832 SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3), 6833 &ShmId, owner); 6834 save_errno = errno; 6835 if (Pshm != NULL || !sm_file_exists(save_errno)) 6836 break; 6837 if (++count >= 3) 6838 { 6839 #if _FFR_SELECT_SHM 6840 if (keyselect) 6841 { 6842 ++ShmKey; 6843 6844 /* back where we started? */ 6845 if (ShmKey == SEL_SHM_KEY) 6846 break; 6847 continue; 6848 } 6849 #endif /* _FFR_SELECT_SHM */ 6850 break; 6851 } 6852 #if _FFR_SELECT_SHM 6853 /* only sleep if we are at the first key */ 6854 if (!keyselect || ShmKey == SEL_SHM_KEY) 6855 #endif /* _FFR_SELECT_SHM */ 6856 sleep(count); 6857 } 6858 if (Pshm != NULL) 6859 { 6860 int *p; 6861 6862 #if _FFR_SELECT_SHM 6863 if (keyselect) 6864 (void) write_key_file(ShmKeyFile, (long) ShmKey); 6865 #endif /* _FFR_SELECT_SHM */ 6866 if (owner && RunAsUid != 0) 6867 { 6868 i = sm_shmsetowner(ShmId, RunAsUid, RunAsGid, 0660); 6869 if (i != 0) 6870 sm_syslog(LOG_ERR, NOQID, 6871 "key=%ld, sm_shmsetowner=%d, RunAsUid=%d, RunAsGid=%d", 6872 (long) ShmKey, i, RunAsUid, RunAsGid); 6873 } 6874 p = (int *) Pshm; 6875 if (owner) 6876 { 6877 *p = (int) shms; 6878 *((pid_t *) SHM_OFF_PID(Pshm)) = CurrentPid; 6879 p = (int *) SHM_OFF_TAG(Pshm); 6880 *p = hash; 6881 } 6882 else 6883 { 6884 if (*p != (int) shms) 6885 { 6886 save_errno = EINVAL; 6887 cleanup_shm(false); 6888 goto error; 6889 } 6890 p = (int *) SHM_OFF_TAG(Pshm); 6891 if (*p != (int) hash) 6892 { 6893 save_errno = EINVAL; 6894 cleanup_shm(false); 6895 goto error; 6896 } 6897 6898 /* 6899 ** XXX how to check the pid? 6900 ** Read it from the pid-file? That does 6901 ** not need to exist. 6902 ** We could disable shm if we can't confirm 6903 ** that it is the right one. 6904 */ 6905 } 6906 6907 PtrFileSys = (FILESYS *) OFF_FILE_SYS(Pshm); 6908 PNumFileSys = (int *) OFF_NUM_FILE_SYS(Pshm); 6909 QShm = (QUEUE_SHM_T *) OFF_QUEUE_SHM(Pshm); 6910 PRSATmpCnt = (int *) OFF_RSA_TMP_CNT(Pshm); 6911 *PRSATmpCnt = 0; 6912 if (owner) 6913 { 6914 /* initialize values in shared memory */ 6915 NumFileSys = 0; 6916 for (i = 0; i < qn; i++) 6917 QShm[i].qs_entries = -1; 6918 } 6919 init_sem(owner); 6920 return; 6921 } 6922 error: 6923 if (LogLevel > (owner ? 8 : 11)) 6924 { 6925 sm_syslog(owner ? LOG_ERR : LOG_NOTICE, NOQID, 6926 "can't %s shared memory, key=%ld: %s", 6927 owner ? "initialize" : "attach to", 6928 (long) ShmKey, sm_errstring(save_errno)); 6929 } 6930 } 6931 #endif /* SM_CONF_SHM */ 6932 6933 6934 /* 6935 ** SETUP_QUEUES -- setup all queue groups 6936 ** 6937 ** Parameters: 6938 ** owner -- owner of shared memory. 6939 ** 6940 ** Returns: 6941 ** none. 6942 ** 6943 #if SM_CONF_SHM 6944 ** Side Effects: 6945 ** attaches shared memory. 6946 #endif * SM_CONF_SHM * 6947 */ 6948 6949 void 6950 setup_queues(owner) 6951 bool owner; 6952 { 6953 int i, qn, len; 6954 unsigned int hashval; 6955 time_t now; 6956 char basedir[MAXPATHLEN]; 6957 struct stat st; 6958 6959 /* 6960 ** Determine basedir for all queue directories. 6961 ** All queue directories must be (first level) subdirectories 6962 ** of the basedir. The basedir is the QueueDir 6963 ** without wildcards, but with trailing / 6964 */ 6965 6966 hashval = 0; 6967 errno = 0; 6968 len = sm_strlcpy(basedir, QueueDir, sizeof basedir); 6969 6970 /* Provide space for trailing '/' */ 6971 if (len >= sizeof basedir - 1) 6972 { 6973 syserr("QueueDirectory: path too long: %d, max %d", 6974 len, (int) sizeof basedir - 1); 6975 ExitStat = EX_CONFIG; 6976 return; 6977 } 6978 SM_ASSERT(len > 0); 6979 if (basedir[len - 1] == '*') 6980 { 6981 char *cp; 6982 6983 cp = SM_LAST_DIR_DELIM(basedir); 6984 if (cp == NULL) 6985 { 6986 syserr("QueueDirectory: can not wildcard relative path \"%s\"", 6987 QueueDir); 6988 if (tTd(41, 2)) 6989 sm_dprintf("setup_queues: \"%s\": Can not wildcard relative path.\n", 6990 QueueDir); 6991 ExitStat = EX_CONFIG; 6992 return; 6993 } 6994 6995 /* cut off wildcard pattern */ 6996 *++cp = '\0'; 6997 len = cp - basedir; 6998 } 6999 else if (!SM_IS_DIR_DELIM(basedir[len - 1])) 7000 { 7001 /* append trailing slash since it is a directory */ 7002 basedir[len] = '/'; 7003 basedir[++len] = '\0'; 7004 } 7005 7006 /* len counts up to the last directory delimiter */ 7007 SM_ASSERT(basedir[len - 1] == '/'); 7008 7009 if (chdir(basedir) < 0) 7010 { 7011 int save_errno = errno; 7012 7013 syserr("can not chdir(%s)", basedir); 7014 if (save_errno == EACCES) 7015 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 7016 "Program mode requires special privileges, e.g., root or TrustedUser.\n"); 7017 if (tTd(41, 2)) 7018 sm_dprintf("setup_queues: \"%s\": %s\n", 7019 basedir, sm_errstring(errno)); 7020 ExitStat = EX_CONFIG; 7021 return; 7022 } 7023 #if SM_CONF_SHM 7024 hashval = hash_q(basedir, hashval); 7025 #endif /* SM_CONF_SHM */ 7026 7027 /* initialize for queue runs */ 7028 DoQueueRun = false; 7029 now = curtime(); 7030 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 7031 Queue[i]->qg_nextrun = now; 7032 7033 7034 if (UseMSP && OpMode != MD_TEST) 7035 { 7036 long sff = SFF_CREAT; 7037 7038 if (stat(".", &st) < 0) 7039 { 7040 syserr("can not stat(%s)", basedir); 7041 if (tTd(41, 2)) 7042 sm_dprintf("setup_queues: \"%s\": %s\n", 7043 basedir, sm_errstring(errno)); 7044 ExitStat = EX_CONFIG; 7045 return; 7046 } 7047 if (RunAsUid == 0) 7048 sff |= SFF_ROOTOK; 7049 7050 /* 7051 ** Check queue directory permissions. 7052 ** Can we write to a group writable queue directory? 7053 */ 7054 7055 if (bitset(S_IWGRP, QueueFileMode) && 7056 bitset(S_IWGRP, st.st_mode) && 7057 safefile(" ", RunAsUid, RunAsGid, RunAsUserName, sff, 7058 QueueFileMode, NULL) != 0) 7059 { 7060 syserr("can not write to queue directory %s (RunAsGid=%d, required=%d)", 7061 basedir, (int) RunAsGid, (int) st.st_gid); 7062 } 7063 if (bitset(S_IWOTH|S_IXOTH, st.st_mode)) 7064 { 7065 #if _FFR_MSP_PARANOIA 7066 syserr("dangerous permissions=%o on queue directory %s", 7067 (int) st.st_mode, basedir); 7068 #else /* _FFR_MSP_PARANOIA */ 7069 if (LogLevel > 0) 7070 sm_syslog(LOG_ERR, NOQID, 7071 "dangerous permissions=%o on queue directory %s", 7072 (int) st.st_mode, basedir); 7073 #endif /* _FFR_MSP_PARANOIA */ 7074 } 7075 #if _FFR_MSP_PARANOIA 7076 if (NumQueue > 1) 7077 syserr("can not use multiple queues for MSP"); 7078 #endif /* _FFR_MSP_PARANOIA */ 7079 } 7080 7081 /* initial number of queue directories */ 7082 qn = 0; 7083 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 7084 qn = multiqueue_cache(basedir, len, Queue[i], qn, &hashval); 7085 7086 #if SM_CONF_SHM 7087 init_shm(qn, owner, hashval); 7088 i = filesys_setup(owner || ShmId == SM_SHM_NO_ID); 7089 if (i == FSF_NOT_FOUND) 7090 { 7091 /* 7092 ** We didn't get the right filesystem data 7093 ** This may happen if we don't have the right shared memory. 7094 ** So let's do this without shared memory. 7095 */ 7096 7097 SM_ASSERT(!owner); 7098 cleanup_shm(false); /* release shared memory */ 7099 i = filesys_setup(false); 7100 if (i < 0) 7101 syserr("filesys_setup failed twice, result=%d", i); 7102 else if (LogLevel > 8) 7103 sm_syslog(LOG_WARNING, NOQID, 7104 "shared memory does not contain expected data, ignored"); 7105 } 7106 #else /* SM_CONF_SHM */ 7107 i = filesys_setup(true); 7108 #endif /* SM_CONF_SHM */ 7109 if (i < 0) 7110 ExitStat = EX_CONFIG; 7111 } 7112 7113 #if SM_CONF_SHM 7114 /* 7115 ** CLEANUP_SHM -- do some cleanup work for shared memory etc 7116 ** 7117 ** Parameters: 7118 ** owner -- owner of shared memory? 7119 ** 7120 ** Returns: 7121 ** none. 7122 ** 7123 ** Side Effects: 7124 ** detaches shared memory. 7125 */ 7126 7127 void 7128 cleanup_shm(owner) 7129 bool owner; 7130 { 7131 if (ShmId != SM_SHM_NO_ID) 7132 { 7133 if (sm_shmstop(Pshm, ShmId, owner) < 0 && LogLevel > 8) 7134 sm_syslog(LOG_INFO, NOQID, "sm_shmstop failed=%s", 7135 sm_errstring(errno)); 7136 Pshm = NULL; 7137 ShmId = SM_SHM_NO_ID; 7138 } 7139 stop_sem(owner); 7140 } 7141 #endif /* SM_CONF_SHM */ 7142 7143 /* 7144 ** CLEANUP_QUEUES -- do some cleanup work for queues 7145 ** 7146 ** Parameters: 7147 ** none. 7148 ** 7149 ** Returns: 7150 ** none. 7151 ** 7152 */ 7153 7154 void 7155 cleanup_queues() 7156 { 7157 sync_queue_time(); 7158 } 7159 /* 7160 ** SET_DEF_QUEUEVAL -- set default values for a queue group. 7161 ** 7162 ** Parameters: 7163 ** qg -- queue group 7164 ** all -- set all values (true for default group)? 7165 ** 7166 ** Returns: 7167 ** none. 7168 ** 7169 ** Side Effects: 7170 ** sets default values for the queue group. 7171 */ 7172 7173 void 7174 set_def_queueval(qg, all) 7175 QUEUEGRP *qg; 7176 bool all; 7177 { 7178 if (bitnset(QD_DEFINED, qg->qg_flags)) 7179 return; 7180 if (all) 7181 qg->qg_qdir = QueueDir; 7182 #if _FFR_QUEUE_GROUP_SORTORDER 7183 qg->qg_sortorder = QueueSortOrder; 7184 #endif /* _FFR_QUEUE_GROUP_SORTORDER */ 7185 qg->qg_maxqrun = all ? MaxRunnersPerQueue : -1; 7186 qg->qg_nice = NiceQueueRun; 7187 } 7188 /* 7189 ** MAKEQUEUE -- define a new queue. 7190 ** 7191 ** Parameters: 7192 ** line -- description of queue. This is in labeled fields. 7193 ** The fields are: 7194 ** F -- the flags associated with the queue 7195 ** I -- the interval between running the queue 7196 ** J -- the maximum # of jobs in work list 7197 ** [M -- the maximum # of jobs in a queue run] 7198 ** N -- the niceness at which to run 7199 ** P -- the path to the queue 7200 ** S -- the queue sorting order 7201 ** R -- number of parallel queue runners 7202 ** r -- max recipients per envelope 7203 ** The first word is the canonical name of the queue. 7204 ** qdef -- this is a 'Q' definition from .cf 7205 ** 7206 ** Returns: 7207 ** none. 7208 ** 7209 ** Side Effects: 7210 ** enters the queue into the queue table. 7211 */ 7212 7213 void 7214 makequeue(line, qdef) 7215 char *line; 7216 bool qdef; 7217 { 7218 register char *p; 7219 register QUEUEGRP *qg; 7220 register STAB *s; 7221 int i; 7222 char fcode; 7223 7224 /* allocate a queue and set up defaults */ 7225 qg = (QUEUEGRP *) xalloc(sizeof *qg); 7226 memset((char *) qg, '\0', sizeof *qg); 7227 7228 if (line[0] == '\0') 7229 { 7230 syserr("name required for queue"); 7231 return; 7232 } 7233 7234 /* collect the queue name */ 7235 for (p = line; 7236 *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); 7237 p++) 7238 continue; 7239 if (*p != '\0') 7240 *p++ = '\0'; 7241 qg->qg_name = newstr(line); 7242 7243 /* set default values, can be overridden below */ 7244 set_def_queueval(qg, false); 7245 7246 /* now scan through and assign info from the fields */ 7247 while (*p != '\0') 7248 { 7249 auto char *delimptr; 7250 7251 while (*p != '\0' && 7252 (*p == ',' || (isascii(*p) && isspace(*p)))) 7253 p++; 7254 7255 /* p now points to field code */ 7256 fcode = *p; 7257 while (*p != '\0' && *p != '=' && *p != ',') 7258 p++; 7259 if (*p++ != '=') 7260 { 7261 syserr("queue %s: `=' expected", qg->qg_name); 7262 return; 7263 } 7264 while (isascii(*p) && isspace(*p)) 7265 p++; 7266 7267 /* p now points to the field body */ 7268 p = munchstring(p, &delimptr, ','); 7269 7270 /* install the field into the queue struct */ 7271 switch (fcode) 7272 { 7273 case 'P': /* pathname */ 7274 if (*p == '\0') 7275 syserr("queue %s: empty path name", 7276 qg->qg_name); 7277 else 7278 qg->qg_qdir = newstr(p); 7279 break; 7280 7281 case 'F': /* flags */ 7282 for (; *p != '\0'; p++) 7283 if (!(isascii(*p) && isspace(*p))) 7284 setbitn(*p, qg->qg_flags); 7285 break; 7286 7287 /* 7288 ** Do we need two intervals here: 7289 ** One for persistent queue runners, 7290 ** one for "normal" queue runs? 7291 */ 7292 7293 case 'I': /* interval between running the queue */ 7294 qg->qg_queueintvl = convtime(p, 'm'); 7295 break; 7296 7297 case 'N': /* run niceness */ 7298 qg->qg_nice = atoi(p); 7299 break; 7300 7301 case 'R': /* maximum # of runners for the group */ 7302 i = atoi(p); 7303 7304 /* can't have more runners than allowed total */ 7305 if (MaxQueueChildren > 0 && i > MaxQueueChildren) 7306 { 7307 qg->qg_maxqrun = MaxQueueChildren; 7308 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 7309 "Q=%s: R=%d exceeds MaxQueueChildren=%d, set to MaxQueueChildren\n", 7310 qg->qg_name, i, 7311 MaxQueueChildren); 7312 } 7313 else 7314 qg->qg_maxqrun = i; 7315 break; 7316 7317 case 'J': /* maximum # of jobs in work list */ 7318 qg->qg_maxlist = atoi(p); 7319 break; 7320 7321 case 'r': /* max recipients per envelope */ 7322 qg->qg_maxrcpt = atoi(p); 7323 break; 7324 7325 #if _FFR_QUEUE_GROUP_SORTORDER 7326 case 'S': /* queue sorting order */ 7327 switch (*p) 7328 { 7329 case 'h': /* Host first */ 7330 case 'H': 7331 qg->qg_sortorder = QSO_BYHOST; 7332 break; 7333 7334 case 'p': /* Priority order */ 7335 case 'P': 7336 qg->qg_sortorder = QSO_BYPRIORITY; 7337 break; 7338 7339 case 't': /* Submission time */ 7340 case 'T': 7341 qg->qg_sortorder = QSO_BYTIME; 7342 break; 7343 7344 case 'f': /* File name */ 7345 case 'F': 7346 qg->qg_sortorder = QSO_BYFILENAME; 7347 break; 7348 7349 case 'm': /* Modification time */ 7350 case 'M': 7351 qg->qg_sortorder = QSO_BYMODTIME; 7352 break; 7353 7354 case 'r': /* Random */ 7355 case 'R': 7356 qg->qg_sortorder = QSO_RANDOM; 7357 break; 7358 7359 # if _FFR_RHS 7360 case 's': /* Shuffled host name */ 7361 case 'S': 7362 qg->qg_sortorder = QSO_BYSHUFFLE; 7363 break; 7364 # endif /* _FFR_RHS */ 7365 7366 case 'n': /* none */ 7367 case 'N': 7368 qg->qg_sortorder = QSO_NONE; 7369 break; 7370 7371 default: 7372 syserr("Invalid queue sort order \"%s\"", p); 7373 } 7374 break; 7375 #endif /* _FFR_QUEUE_GROUP_SORTORDER */ 7376 7377 default: 7378 syserr("Q%s: unknown queue equate %c=", 7379 qg->qg_name, fcode); 7380 break; 7381 } 7382 7383 p = delimptr; 7384 } 7385 7386 #if !HASNICE 7387 if (qg->qg_nice != NiceQueueRun) 7388 { 7389 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 7390 "Q%s: Warning: N= set on system that doesn't support nice()\n", 7391 qg->qg_name); 7392 } 7393 #endif /* !HASNICE */ 7394 7395 /* do some rationality checking */ 7396 if (NumQueue >= MAXQUEUEGROUPS) 7397 { 7398 syserr("too many queue groups defined (%d max)", 7399 MAXQUEUEGROUPS); 7400 return; 7401 } 7402 7403 if (qg->qg_qdir == NULL) 7404 { 7405 if (QueueDir == NULL || *QueueDir == '\0') 7406 { 7407 syserr("QueueDir must be defined before queue groups"); 7408 return; 7409 } 7410 qg->qg_qdir = newstr(QueueDir); 7411 } 7412 7413 if (qg->qg_maxqrun > 1 && !bitnset(QD_FORK, qg->qg_flags)) 7414 { 7415 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 7416 "Warning: Q=%s: R=%d: multiple queue runners specified\n\tbut flag '%c' is not set\n", 7417 qg->qg_name, qg->qg_maxqrun, QD_FORK); 7418 } 7419 7420 /* enter the queue into the symbol table */ 7421 if (tTd(37, 8)) 7422 sm_syslog(LOG_INFO, NOQID, 7423 "Adding %s to stab, path: %s", qg->qg_name, 7424 qg->qg_qdir); 7425 s = stab(qg->qg_name, ST_QUEUE, ST_ENTER); 7426 if (s->s_quegrp != NULL) 7427 { 7428 i = s->s_quegrp->qg_index; 7429 7430 /* XXX what about the pointers inside this struct? */ 7431 sm_free(s->s_quegrp); /* XXX */ 7432 } 7433 else 7434 i = NumQueue++; 7435 Queue[i] = s->s_quegrp = qg; 7436 qg->qg_index = i; 7437 7438 /* set default value for max queue runners */ 7439 if (qg->qg_maxqrun < 0) 7440 { 7441 if (MaxRunnersPerQueue > 0) 7442 qg->qg_maxqrun = MaxRunnersPerQueue; 7443 else 7444 qg->qg_maxqrun = 1; 7445 } 7446 if (qdef) 7447 setbitn(QD_DEFINED, qg->qg_flags); 7448 } 7449 #if 0 7450 /* 7451 ** HASHFQN -- calculate a hash value for a fully qualified host name 7452 ** 7453 ** Arguments: 7454 ** fqn -- an all lower-case host.domain string 7455 ** buckets -- the number of buckets (queue directories) 7456 ** 7457 ** Returns: 7458 ** a bucket number (signed integer) 7459 ** -1 on error 7460 ** 7461 ** Contributed by Exactis.com, Inc. 7462 */ 7463 7464 int 7465 hashfqn(fqn, buckets) 7466 register char *fqn; 7467 int buckets; 7468 { 7469 register char *p; 7470 register int h = 0, hash, cnt; 7471 7472 if (fqn == NULL) 7473 return -1; 7474 7475 /* 7476 ** A variation on the gdb hash 7477 ** This is the best as of Feb 19, 1996 --bcx 7478 */ 7479 7480 p = fqn; 7481 h = 0x238F13AF * strlen(p); 7482 for (cnt = 0; *p != 0; ++p, cnt++) 7483 { 7484 h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF; 7485 } 7486 h = (1103515243 * h + 12345) & 0x7FFFFFFF; 7487 if (buckets < 2) 7488 hash = 0; 7489 else 7490 hash = (h % buckets); 7491 7492 return hash; 7493 } 7494 #endif /* 0 */ 7495 7496 /* 7497 ** A structure for sorting Queue according to maxqrun without 7498 ** screwing up Queue itself. 7499 */ 7500 7501 struct sortqgrp 7502 { 7503 int sg_idx; /* original index */ 7504 int sg_maxqrun; /* max queue runners */ 7505 }; 7506 typedef struct sortqgrp SORTQGRP_T; 7507 static int cmpidx __P((const void *, const void *)); 7508 7509 static int 7510 cmpidx(a, b) 7511 const void *a; 7512 const void *b; 7513 { 7514 /* The sort is highest to lowest, so the comparison is reversed */ 7515 if (((SORTQGRP_T *)a)->sg_maxqrun < ((SORTQGRP_T *)b)->sg_maxqrun) 7516 return 1; 7517 else if (((SORTQGRP_T *)a)->sg_maxqrun > ((SORTQGRP_T *)b)->sg_maxqrun) 7518 return -1; 7519 else 7520 return 0; 7521 } 7522 7523 /* 7524 ** MAKEWORKGROUP -- balance queue groups into work groups per MaxQueueChildren 7525 ** 7526 ** Take the now defined queue groups and assign them to work groups. 7527 ** This is done to balance out the number of concurrently active 7528 ** queue runners such that MaxQueueChildren is not exceeded. This may 7529 ** result in more than one queue group per work group. In such a case 7530 ** the number of running queue groups in that work group will have no 7531 ** more than the work group maximum number of runners (a "fair" portion 7532 ** of MaxQueueRunners). All queue groups within a work group will get a 7533 ** chance at running. 7534 ** 7535 ** Parameters: 7536 ** none. 7537 ** 7538 ** Returns: 7539 ** nothing. 7540 ** 7541 ** Side Effects: 7542 ** Sets up WorkGrp structure. 7543 */ 7544 7545 void 7546 makeworkgroups() 7547 { 7548 int i, j, total_runners, dir, h; 7549 SORTQGRP_T si[MAXQUEUEGROUPS + 1]; 7550 7551 total_runners = 0; 7552 if (NumQueue == 1 && strcmp(Queue[0]->qg_name, "mqueue") == 0) 7553 { 7554 /* 7555 ** There is only the "mqueue" queue group (a default) 7556 ** containing all of the queues. We want to provide to 7557 ** this queue group the maximum allowable queue runners. 7558 ** To match older behavior (8.10/8.11) we'll try for 7559 ** 1 runner per queue capping it at MaxQueueChildren. 7560 ** So if there are N queues, then there will be N runners 7561 ** for the "mqueue" queue group (where N is kept less than 7562 ** MaxQueueChildren). 7563 */ 7564 7565 NumWorkGroups = 1; 7566 WorkGrp[0].wg_numqgrp = 1; 7567 WorkGrp[0].wg_qgs = (QUEUEGRP **) xalloc(sizeof(QUEUEGRP *)); 7568 WorkGrp[0].wg_qgs[0] = Queue[0]; 7569 if (MaxQueueChildren > 0 && 7570 Queue[0]->qg_numqueues > MaxQueueChildren) 7571 WorkGrp[0].wg_runners = MaxQueueChildren; 7572 else 7573 WorkGrp[0].wg_runners = Queue[0]->qg_numqueues; 7574 7575 Queue[0]->qg_wgrp = 0; 7576 7577 /* can't have more runners than allowed total */ 7578 if (MaxQueueChildren > 0 && 7579 Queue[0]->qg_maxqrun > MaxQueueChildren) 7580 Queue[0]->qg_maxqrun = MaxQueueChildren; 7581 WorkGrp[0].wg_maxact = Queue[0]->qg_maxqrun; 7582 WorkGrp[0].wg_lowqintvl = Queue[0]->qg_queueintvl; 7583 return; 7584 } 7585 7586 for (i = 0; i < NumQueue; i++) 7587 { 7588 si[i].sg_maxqrun = Queue[i]->qg_maxqrun; 7589 si[i].sg_idx = i; 7590 } 7591 qsort(si, NumQueue, sizeof(si[0]), cmpidx); 7592 7593 NumWorkGroups = 0; 7594 for (i = 0; i < NumQueue; i++) 7595 { 7596 total_runners += si[i].sg_maxqrun; 7597 if (MaxQueueChildren <= 0 || total_runners <= MaxQueueChildren) 7598 NumWorkGroups++; 7599 else 7600 break; 7601 } 7602 7603 if (NumWorkGroups < 1) 7604 NumWorkGroups = 1; /* gotta have one at least */ 7605 else if (NumWorkGroups > MAXWORKGROUPS) 7606 NumWorkGroups = MAXWORKGROUPS; /* the limit */ 7607 7608 /* 7609 ** We now know the number of work groups to pack the queue groups 7610 ** into. The queue groups in 'Queue' are sorted from highest 7611 ** to lowest for the number of runners per queue group. 7612 ** We put the queue groups with the largest number of runners 7613 ** into work groups first. Then the smaller ones are fitted in 7614 ** where it looks best. 7615 */ 7616 7617 j = 0; 7618 dir = 1; 7619 for (i = 0; i < NumQueue; i++) 7620 { 7621 /* a to-and-fro packing scheme, continue from last position */ 7622 if (j >= NumWorkGroups) 7623 { 7624 dir = -1; 7625 j = NumWorkGroups - 1; 7626 } 7627 else if (j < 0) 7628 { 7629 j = 0; 7630 dir = 1; 7631 } 7632 7633 if (WorkGrp[j].wg_qgs == NULL) 7634 WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_malloc(sizeof(QUEUEGRP *) * 7635 (WorkGrp[j].wg_numqgrp + 1)); 7636 else 7637 WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_realloc(WorkGrp[j].wg_qgs, 7638 sizeof(QUEUEGRP *) * 7639 (WorkGrp[j].wg_numqgrp + 1)); 7640 if (WorkGrp[j].wg_qgs == NULL) 7641 { 7642 syserr("!cannot allocate memory for work queues, need %d bytes", 7643 (int) (sizeof(QUEUEGRP *) * 7644 (WorkGrp[j].wg_numqgrp + 1))); 7645 } 7646 7647 h = si[i].sg_idx; 7648 WorkGrp[j].wg_qgs[WorkGrp[j].wg_numqgrp] = Queue[h]; 7649 WorkGrp[j].wg_numqgrp++; 7650 WorkGrp[j].wg_runners += Queue[h]->qg_maxqrun; 7651 Queue[h]->qg_wgrp = j; 7652 7653 if (WorkGrp[j].wg_maxact == 0) 7654 { 7655 /* can't have more runners than allowed total */ 7656 if (MaxQueueChildren > 0 && 7657 Queue[h]->qg_maxqrun > MaxQueueChildren) 7658 Queue[h]->qg_maxqrun = MaxQueueChildren; 7659 WorkGrp[j].wg_maxact = Queue[h]->qg_maxqrun; 7660 } 7661 7662 /* 7663 ** XXX: must wg_lowqintvl be the GCD? 7664 ** qg1: 2m, qg2: 3m, minimum: 2m, when do queue runs for 7665 ** qg2 occur? 7666 */ 7667 7668 /* keep track of the lowest interval for a persistent runner */ 7669 if (Queue[h]->qg_queueintvl > 0 && 7670 WorkGrp[j].wg_lowqintvl < Queue[h]->qg_queueintvl) 7671 WorkGrp[j].wg_lowqintvl = Queue[h]->qg_queueintvl; 7672 j += dir; 7673 } 7674 if (tTd(41, 9)) 7675 { 7676 for (i = 0; i < NumWorkGroups; i++) 7677 { 7678 sm_dprintf("Workgroup[%d]=", i); 7679 for (j = 0; j < WorkGrp[i].wg_numqgrp; j++) 7680 { 7681 sm_dprintf("%s, ", 7682 WorkGrp[i].wg_qgs[j]->qg_name); 7683 } 7684 sm_dprintf("\n"); 7685 } 7686 } 7687 } 7688 7689 /* 7690 ** DUP_DF -- duplicate envelope data file 7691 ** 7692 ** Copy the data file from the 'old' envelope to the 'new' envelope 7693 ** in the most efficient way possible. 7694 ** 7695 ** Create a hard link from the 'old' data file to the 'new' data file. 7696 ** If the old and new queue directories are on different file systems, 7697 ** then the new data file link is created in the old queue directory, 7698 ** and the new queue file will contain a 'd' record pointing to the 7699 ** directory containing the new data file. 7700 ** 7701 ** Parameters: 7702 ** old -- old envelope. 7703 ** new -- new envelope. 7704 ** 7705 ** Results: 7706 ** Returns true on success, false on failure. 7707 ** 7708 ** Side Effects: 7709 ** On success, the new data file is created. 7710 ** On fatal failure, EF_FATALERRS is set in old->e_flags. 7711 */ 7712 7713 static bool dup_df __P((ENVELOPE *, ENVELOPE *)); 7714 7715 static bool 7716 dup_df(old, new) 7717 ENVELOPE *old; 7718 ENVELOPE *new; 7719 { 7720 int ofs, nfs, r; 7721 char opath[MAXPATHLEN]; 7722 char npath[MAXPATHLEN]; 7723 7724 if (!bitset(EF_HAS_DF, old->e_flags)) 7725 { 7726 /* 7727 ** this can happen if: SuperSafe != True 7728 ** and a bounce mail is sent that is split. 7729 */ 7730 7731 queueup(old, false, true); 7732 } 7733 SM_REQUIRE(ISVALIDQGRP(old->e_qgrp) && ISVALIDQDIR(old->e_qdir)); 7734 SM_REQUIRE(ISVALIDQGRP(new->e_qgrp) && ISVALIDQDIR(new->e_qdir)); 7735 7736 (void) sm_strlcpy(opath, queuename(old, DATAFL_LETTER), sizeof opath); 7737 (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof npath); 7738 7739 if (old->e_dfp != NULL) 7740 { 7741 r = sm_io_setinfo(old->e_dfp, SM_BF_COMMIT, NULL); 7742 if (r < 0 && errno != EINVAL) 7743 { 7744 syserr("@can't commit %s", opath); 7745 old->e_flags |= EF_FATALERRS; 7746 return false; 7747 } 7748 } 7749 7750 /* 7751 ** Attempt to create a hard link, if we think both old and new 7752 ** are on the same file system, otherwise copy the file. 7753 ** 7754 ** Don't waste time attempting a hard link unless old and new 7755 ** are on the same file system. 7756 */ 7757 7758 SM_REQUIRE(ISVALIDQGRP(old->e_dfqgrp) && ISVALIDQDIR(old->e_dfqdir)); 7759 SM_REQUIRE(ISVALIDQGRP(new->e_dfqgrp) && ISVALIDQDIR(new->e_dfqdir)); 7760 7761 ofs = Queue[old->e_dfqgrp]->qg_qpaths[old->e_dfqdir].qp_fsysidx; 7762 nfs = Queue[new->e_dfqgrp]->qg_qpaths[new->e_dfqdir].qp_fsysidx; 7763 if (FILE_SYS_DEV(ofs) == FILE_SYS_DEV(nfs)) 7764 { 7765 if (link(opath, npath) == 0) 7766 { 7767 new->e_flags |= EF_HAS_DF; 7768 SYNC_DIR(npath, true); 7769 return true; 7770 } 7771 goto error; 7772 } 7773 7774 /* 7775 ** Can't link across queue directories, so try to create a hard 7776 ** link in the same queue directory as the old df file. 7777 ** The qf file will refer to the new df file using a 'd' record. 7778 */ 7779 7780 new->e_dfqgrp = old->e_dfqgrp; 7781 new->e_dfqdir = old->e_dfqdir; 7782 (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof npath); 7783 if (link(opath, npath) == 0) 7784 { 7785 new->e_flags |= EF_HAS_DF; 7786 SYNC_DIR(npath, true); 7787 return true; 7788 } 7789 7790 error: 7791 if (LogLevel > 0) 7792 sm_syslog(LOG_ERR, old->e_id, 7793 "dup_df: can't link %s to %s, error=%s, envelope splitting failed", 7794 opath, npath, sm_errstring(errno)); 7795 return false; 7796 } 7797 7798 /* 7799 ** SPLIT_ENV -- Allocate a new envelope based on a given envelope. 7800 ** 7801 ** Parameters: 7802 ** e -- envelope. 7803 ** sendqueue -- sendqueue for new envelope. 7804 ** qgrp -- index of queue group. 7805 ** qdir -- queue directory. 7806 ** 7807 ** Results: 7808 ** new envelope. 7809 ** 7810 */ 7811 7812 static ENVELOPE *split_env __P((ENVELOPE *, ADDRESS *, int, int)); 7813 7814 static ENVELOPE * 7815 split_env(e, sendqueue, qgrp, qdir) 7816 ENVELOPE *e; 7817 ADDRESS *sendqueue; 7818 int qgrp; 7819 int qdir; 7820 { 7821 ENVELOPE *ee; 7822 7823 ee = (ENVELOPE *) sm_rpool_malloc_x(e->e_rpool, sizeof *ee); 7824 STRUCTCOPY(*e, *ee); 7825 ee->e_message = NULL; /* XXX use original message? */ 7826 ee->e_id = NULL; 7827 assign_queueid(ee); 7828 ee->e_sendqueue = sendqueue; 7829 ee->e_flags &= ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS 7830 |EF_SENDRECEIPT|EF_RET_PARAM|EF_HAS_DF); 7831 ee->e_flags |= EF_NORECEIPT; /* XXX really? */ 7832 ee->e_from.q_state = QS_SENDER; 7833 ee->e_dfp = NULL; 7834 ee->e_lockfp = NULL; 7835 if (e->e_xfp != NULL) 7836 ee->e_xfp = sm_io_dup(e->e_xfp); 7837 7838 /* failed to dup e->e_xfp, start a new transcript */ 7839 if (ee->e_xfp == NULL) 7840 openxscript(ee); 7841 7842 ee->e_qgrp = ee->e_dfqgrp = qgrp; 7843 ee->e_qdir = ee->e_dfqdir = qdir; 7844 ee->e_errormode = EM_MAIL; 7845 ee->e_statmsg = NULL; 7846 if (e->e_quarmsg != NULL) 7847 ee->e_quarmsg = sm_rpool_strdup_x(ee->e_rpool, 7848 e->e_quarmsg); 7849 7850 /* 7851 ** XXX Not sure if this copying is necessary. 7852 ** sendall() does this copying, but I (dm) don't know if that is 7853 ** because of the storage management discipline we were using 7854 ** before rpools were introduced, or if it is because these lists 7855 ** can be modified later. 7856 */ 7857 7858 ee->e_header = copyheader(e->e_header, ee->e_rpool); 7859 ee->e_errorqueue = copyqueue(e->e_errorqueue, ee->e_rpool); 7860 7861 return ee; 7862 } 7863 7864 /* return values from split functions, check also below! */ 7865 #define SM_SPLIT_FAIL (0) 7866 #define SM_SPLIT_NONE (1) 7867 #define SM_SPLIT_NEW(n) (1 + (n)) 7868 7869 /* 7870 ** SPLIT_ACROSS_QUEUE_GROUPS 7871 ** 7872 ** This function splits an envelope across multiple queue groups 7873 ** based on the queue group of each recipient. 7874 ** 7875 ** Parameters: 7876 ** e -- envelope. 7877 ** 7878 ** Results: 7879 ** SM_SPLIT_FAIL on failure 7880 ** SM_SPLIT_NONE if no splitting occurred, 7881 ** or 1 + the number of additional envelopes created. 7882 ** 7883 ** Side Effects: 7884 ** On success, e->e_sibling points to a list of zero or more 7885 ** additional envelopes, and the associated data files exist 7886 ** on disk. But the queue files are not created. 7887 ** 7888 ** On failure, e->e_sibling is not changed. 7889 ** The order of recipients in e->e_sendqueue is permuted. 7890 ** Abandoned data files for additional envelopes that failed 7891 ** to be created may exist on disk. 7892 */ 7893 7894 static int q_qgrp_compare __P((const void *, const void *)); 7895 static int e_filesys_compare __P((const void *, const void *)); 7896 7897 static int 7898 q_qgrp_compare(p1, p2) 7899 const void *p1; 7900 const void *p2; 7901 { 7902 ADDRESS **pq1 = (ADDRESS **) p1; 7903 ADDRESS **pq2 = (ADDRESS **) p2; 7904 7905 return (*pq1)->q_qgrp - (*pq2)->q_qgrp; 7906 } 7907 7908 static int 7909 e_filesys_compare(p1, p2) 7910 const void *p1; 7911 const void *p2; 7912 { 7913 ENVELOPE **pe1 = (ENVELOPE **) p1; 7914 ENVELOPE **pe2 = (ENVELOPE **) p2; 7915 int fs1, fs2; 7916 7917 fs1 = Queue[(*pe1)->e_qgrp]->qg_qpaths[(*pe1)->e_qdir].qp_fsysidx; 7918 fs2 = Queue[(*pe2)->e_qgrp]->qg_qpaths[(*pe2)->e_qdir].qp_fsysidx; 7919 if (FILE_SYS_DEV(fs1) < FILE_SYS_DEV(fs2)) 7920 return -1; 7921 if (FILE_SYS_DEV(fs1) > FILE_SYS_DEV(fs2)) 7922 return 1; 7923 return 0; 7924 } 7925 7926 static int 7927 split_across_queue_groups(e) 7928 ENVELOPE *e; 7929 { 7930 int naddrs, nsplits, i; 7931 bool changed; 7932 char **pvp; 7933 ADDRESS *q, **addrs; 7934 ENVELOPE *ee, *es; 7935 ENVELOPE *splits[MAXQUEUEGROUPS]; 7936 char pvpbuf[PSBUFSIZE]; 7937 7938 SM_REQUIRE(ISVALIDQGRP(e->e_qgrp)); 7939 7940 /* Count addresses and assign queue groups. */ 7941 naddrs = 0; 7942 changed = false; 7943 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 7944 { 7945 if (QS_IS_DEAD(q->q_state)) 7946 continue; 7947 ++naddrs; 7948 7949 /* bad addresses and those already sent stay put */ 7950 if (QS_IS_BADADDR(q->q_state) || 7951 QS_IS_SENT(q->q_state)) 7952 q->q_qgrp = e->e_qgrp; 7953 else if (!ISVALIDQGRP(q->q_qgrp)) 7954 { 7955 /* call ruleset which should return a queue group */ 7956 i = rscap(RS_QUEUEGROUP, q->q_user, NULL, e, &pvp, 7957 pvpbuf, sizeof(pvpbuf)); 7958 if (i == EX_OK && 7959 pvp != NULL && pvp[0] != NULL && 7960 (pvp[0][0] & 0377) == CANONNET && 7961 pvp[1] != NULL && pvp[1][0] != '\0') 7962 { 7963 i = name2qid(pvp[1]); 7964 if (ISVALIDQGRP(i)) 7965 { 7966 q->q_qgrp = i; 7967 changed = true; 7968 if (tTd(20, 4)) 7969 sm_syslog(LOG_INFO, NOQID, 7970 "queue group name %s -> %d", 7971 pvp[1], i); 7972 continue; 7973 } 7974 else if (LogLevel > 10) 7975 sm_syslog(LOG_INFO, NOQID, 7976 "can't find queue group name %s, selection ignored", 7977 pvp[1]); 7978 } 7979 if (q->q_mailer != NULL && 7980 ISVALIDQGRP(q->q_mailer->m_qgrp)) 7981 { 7982 changed = true; 7983 q->q_qgrp = q->q_mailer->m_qgrp; 7984 } 7985 else if (ISVALIDQGRP(e->e_qgrp)) 7986 q->q_qgrp = e->e_qgrp; 7987 else 7988 q->q_qgrp = 0; 7989 } 7990 } 7991 7992 /* only one address? nothing to split. */ 7993 if (naddrs <= 1 && !changed) 7994 return SM_SPLIT_NONE; 7995 7996 /* sort the addresses by queue group */ 7997 addrs = sm_rpool_malloc_x(e->e_rpool, naddrs * sizeof(ADDRESS *)); 7998 for (i = 0, q = e->e_sendqueue; q != NULL; q = q->q_next) 7999 { 8000 if (QS_IS_DEAD(q->q_state)) 8001 continue; 8002 addrs[i++] = q; 8003 } 8004 qsort(addrs, naddrs, sizeof(ADDRESS *), q_qgrp_compare); 8005 8006 /* split into multiple envelopes, by queue group */ 8007 nsplits = 0; 8008 es = NULL; 8009 e->e_sendqueue = NULL; 8010 for (i = 0; i < naddrs; ++i) 8011 { 8012 if (i == naddrs - 1 || addrs[i]->q_qgrp != addrs[i + 1]->q_qgrp) 8013 addrs[i]->q_next = NULL; 8014 else 8015 addrs[i]->q_next = addrs[i + 1]; 8016 8017 /* same queue group as original envelope? */ 8018 if (addrs[i]->q_qgrp == e->e_qgrp) 8019 { 8020 if (e->e_sendqueue == NULL) 8021 e->e_sendqueue = addrs[i]; 8022 continue; 8023 } 8024 8025 /* different queue group than original envelope */ 8026 if (es == NULL || addrs[i]->q_qgrp != es->e_qgrp) 8027 { 8028 ee = split_env(e, addrs[i], addrs[i]->q_qgrp, NOQDIR); 8029 es = ee; 8030 splits[nsplits++] = ee; 8031 } 8032 } 8033 8034 /* no splits? return right now. */ 8035 if (nsplits <= 0) 8036 return SM_SPLIT_NONE; 8037 8038 /* assign a queue directory to each additional envelope */ 8039 for (i = 0; i < nsplits; ++i) 8040 { 8041 es = splits[i]; 8042 #if 0 8043 es->e_qdir = pickqdir(Queue[es->e_qgrp], es->e_msgsize, es); 8044 #endif /* 0 */ 8045 if (!setnewqueue(es)) 8046 goto failure; 8047 } 8048 8049 /* sort the additional envelopes by queue file system */ 8050 qsort(splits, nsplits, sizeof(ENVELOPE *), e_filesys_compare); 8051 8052 /* create data files for each additional envelope */ 8053 if (!dup_df(e, splits[0])) 8054 { 8055 i = 0; 8056 goto failure; 8057 } 8058 for (i = 1; i < nsplits; ++i) 8059 { 8060 /* copy or link to the previous data file */ 8061 if (!dup_df(splits[i - 1], splits[i])) 8062 goto failure; 8063 } 8064 8065 /* success: prepend the new envelopes to the e->e_sibling list */ 8066 for (i = 0; i < nsplits; ++i) 8067 { 8068 es = splits[i]; 8069 es->e_sibling = e->e_sibling; 8070 e->e_sibling = es; 8071 } 8072 return SM_SPLIT_NEW(nsplits); 8073 8074 /* failure: clean up */ 8075 failure: 8076 if (i > 0) 8077 { 8078 int j; 8079 8080 for (j = 0; j < i; j++) 8081 (void) unlink(queuename(splits[j], DATAFL_LETTER)); 8082 } 8083 e->e_sendqueue = addrs[0]; 8084 for (i = 0; i < naddrs - 1; ++i) 8085 addrs[i]->q_next = addrs[i + 1]; 8086 addrs[naddrs - 1]->q_next = NULL; 8087 return SM_SPLIT_FAIL; 8088 } 8089 8090 /* 8091 ** SPLIT_WITHIN_QUEUE 8092 ** 8093 ** Split an envelope with multiple recipients into several 8094 ** envelopes within the same queue directory, if the number of 8095 ** recipients exceeds the limit for the queue group. 8096 ** 8097 ** Parameters: 8098 ** e -- envelope. 8099 ** 8100 ** Results: 8101 ** SM_SPLIT_FAIL on failure 8102 ** SM_SPLIT_NONE if no splitting occurred, 8103 ** or 1 + the number of additional envelopes created. 8104 */ 8105 8106 #define SPLIT_LOG_LEVEL 8 8107 8108 static int split_within_queue __P((ENVELOPE *)); 8109 8110 static int 8111 split_within_queue(e) 8112 ENVELOPE *e; 8113 { 8114 int maxrcpt, nrcpt, ndead, nsplit, i; 8115 int j, l; 8116 char *lsplits; 8117 ADDRESS *q, **addrs; 8118 ENVELOPE *ee, *firstsibling; 8119 8120 if (!ISVALIDQGRP(e->e_qgrp) || bitset(EF_SPLIT, e->e_flags)) 8121 return SM_SPLIT_NONE; 8122 8123 /* don't bother if there is no recipient limit */ 8124 maxrcpt = Queue[e->e_qgrp]->qg_maxrcpt; 8125 if (maxrcpt <= 0) 8126 return SM_SPLIT_NONE; 8127 8128 /* count recipients */ 8129 nrcpt = 0; 8130 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 8131 { 8132 if (QS_IS_DEAD(q->q_state)) 8133 continue; 8134 ++nrcpt; 8135 } 8136 if (nrcpt <= maxrcpt) 8137 return SM_SPLIT_NONE; 8138 8139 /* 8140 ** Preserve the recipient list 8141 ** so that we can restore it in case of error. 8142 ** (But we discard dead addresses.) 8143 */ 8144 8145 addrs = sm_rpool_malloc_x(e->e_rpool, nrcpt * sizeof(ADDRESS *)); 8146 for (i = 0, q = e->e_sendqueue; q != NULL; q = q->q_next) 8147 { 8148 if (QS_IS_DEAD(q->q_state)) 8149 continue; 8150 addrs[i++] = q; 8151 } 8152 8153 /* 8154 ** Partition the recipient list so that bad and sent addresses 8155 ** come first. These will go with the original envelope, and 8156 ** do not count towards the maxrcpt limit. 8157 ** addrs[] does not contain QS_IS_DEAD() addresses. 8158 */ 8159 8160 ndead = 0; 8161 for (i = 0; i < nrcpt; ++i) 8162 { 8163 if (QS_IS_BADADDR(addrs[i]->q_state) || 8164 QS_IS_SENT(addrs[i]->q_state) || 8165 QS_IS_DEAD(addrs[i]->q_state)) /* for paranoia's sake */ 8166 { 8167 if (i > ndead) 8168 { 8169 ADDRESS *tmp = addrs[i]; 8170 8171 addrs[i] = addrs[ndead]; 8172 addrs[ndead] = tmp; 8173 } 8174 ++ndead; 8175 } 8176 } 8177 8178 /* Check if no splitting required. */ 8179 if (nrcpt - ndead <= maxrcpt) 8180 return SM_SPLIT_NONE; 8181 8182 /* fix links */ 8183 for (i = 0; i < nrcpt - 1; ++i) 8184 addrs[i]->q_next = addrs[i + 1]; 8185 addrs[nrcpt - 1]->q_next = NULL; 8186 e->e_sendqueue = addrs[0]; 8187 8188 /* prepare buffer for logging */ 8189 if (LogLevel > SPLIT_LOG_LEVEL) 8190 { 8191 l = MAXLINE; 8192 lsplits = sm_malloc(l); 8193 if (lsplits != NULL) 8194 *lsplits = '\0'; 8195 j = 0; 8196 } 8197 else 8198 { 8199 /* get rid of stupid compiler warnings */ 8200 lsplits = NULL; 8201 j = l = 0; 8202 } 8203 8204 /* split the envelope */ 8205 firstsibling = e->e_sibling; 8206 i = maxrcpt + ndead; 8207 nsplit = 0; 8208 for (;;) 8209 { 8210 addrs[i - 1]->q_next = NULL; 8211 ee = split_env(e, addrs[i], e->e_qgrp, e->e_qdir); 8212 if (!dup_df(e, ee)) 8213 { 8214 8215 ee = firstsibling; 8216 while (ee != NULL) 8217 { 8218 (void) unlink(queuename(ee, DATAFL_LETTER)); 8219 ee = ee->e_sibling; 8220 } 8221 8222 /* Error. Restore e's sibling & recipient lists. */ 8223 e->e_sibling = firstsibling; 8224 for (i = 0; i < nrcpt - 1; ++i) 8225 addrs[i]->q_next = addrs[i + 1]; 8226 if (lsplits != NULL) 8227 sm_free(lsplits); 8228 return SM_SPLIT_FAIL; 8229 } 8230 8231 /* prepend the new envelope to e->e_sibling */ 8232 ee->e_sibling = e->e_sibling; 8233 e->e_sibling = ee; 8234 ++nsplit; 8235 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL) 8236 { 8237 if (j >= l - strlen(ee->e_id) - 3) 8238 { 8239 char *p; 8240 8241 l += MAXLINE; 8242 p = sm_realloc(lsplits, l); 8243 if (p == NULL) 8244 { 8245 /* let's try to get this done */ 8246 sm_free(lsplits); 8247 lsplits = NULL; 8248 } 8249 else 8250 lsplits = p; 8251 } 8252 if (lsplits != NULL) 8253 { 8254 if (j == 0) 8255 j += sm_strlcat(lsplits + j, 8256 ee->e_id, 8257 l - j); 8258 else 8259 j += sm_strlcat2(lsplits + j, 8260 "; ", 8261 ee->e_id, 8262 l - j); 8263 SM_ASSERT(j < l); 8264 } 8265 } 8266 if (nrcpt - i <= maxrcpt) 8267 break; 8268 i += maxrcpt; 8269 } 8270 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL) 8271 { 8272 if (nsplit > 0) 8273 { 8274 sm_syslog(LOG_NOTICE, e->e_id, 8275 "split: maxrcpts=%d, rcpts=%d, count=%d, id%s=%s", 8276 maxrcpt, nrcpt - ndead, nsplit, 8277 nsplit > 1 ? "s" : "", lsplits); 8278 } 8279 sm_free(lsplits); 8280 } 8281 return SM_SPLIT_NEW(nsplit); 8282 } 8283 /* 8284 ** SPLIT_BY_RECIPIENT 8285 ** 8286 ** Split an envelope with multiple recipients into multiple 8287 ** envelopes as required by the sendmail configuration. 8288 ** 8289 ** Parameters: 8290 ** e -- envelope. 8291 ** 8292 ** Results: 8293 ** Returns true on success, false on failure. 8294 ** 8295 ** Side Effects: 8296 ** see split_across_queue_groups(), split_within_queue(e) 8297 */ 8298 8299 bool 8300 split_by_recipient(e) 8301 ENVELOPE *e; 8302 { 8303 int split, n, i, j, l; 8304 char *lsplits; 8305 ENVELOPE *ee, *next, *firstsibling; 8306 8307 if (OpMode == SM_VERIFY || !ISVALIDQGRP(e->e_qgrp) || 8308 bitset(EF_SPLIT, e->e_flags)) 8309 return true; 8310 n = split_across_queue_groups(e); 8311 if (n == SM_SPLIT_FAIL) 8312 return false; 8313 firstsibling = ee = e->e_sibling; 8314 if (n > 1 && LogLevel > SPLIT_LOG_LEVEL) 8315 { 8316 l = MAXLINE; 8317 lsplits = sm_malloc(l); 8318 if (lsplits != NULL) 8319 *lsplits = '\0'; 8320 j = 0; 8321 } 8322 else 8323 { 8324 /* get rid of stupid compiler warnings */ 8325 lsplits = NULL; 8326 j = l = 0; 8327 } 8328 for (i = 1; i < n; ++i) 8329 { 8330 next = ee->e_sibling; 8331 if (split_within_queue(ee) == SM_SPLIT_FAIL) 8332 { 8333 e->e_sibling = firstsibling; 8334 return false; 8335 } 8336 ee->e_flags |= EF_SPLIT; 8337 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL) 8338 { 8339 if (j >= l - strlen(ee->e_id) - 3) 8340 { 8341 char *p; 8342 8343 l += MAXLINE; 8344 p = sm_realloc(lsplits, l); 8345 if (p == NULL) 8346 { 8347 /* let's try to get this done */ 8348 sm_free(lsplits); 8349 lsplits = NULL; 8350 } 8351 else 8352 lsplits = p; 8353 } 8354 if (lsplits != NULL) 8355 { 8356 if (j == 0) 8357 j += sm_strlcat(lsplits + j, 8358 ee->e_id, l - j); 8359 else 8360 j += sm_strlcat2(lsplits + j, "; ", 8361 ee->e_id, l - j); 8362 SM_ASSERT(j < l); 8363 } 8364 } 8365 ee = next; 8366 } 8367 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL && n > 1) 8368 { 8369 sm_syslog(LOG_NOTICE, e->e_id, "split: count=%d, id%s=%s", 8370 n - 1, n > 2 ? "s" : "", lsplits); 8371 sm_free(lsplits); 8372 } 8373 split = split_within_queue(e) != SM_SPLIT_FAIL; 8374 if (split) 8375 e->e_flags |= EF_SPLIT; 8376 return split; 8377 } 8378 8379 /* 8380 ** QUARANTINE_QUEUE_ITEM -- {un,}quarantine a single envelope 8381 ** 8382 ** Add/remove quarantine reason and requeue appropriately. 8383 ** 8384 ** Parameters: 8385 ** qgrp -- queue group for the item 8386 ** qdir -- queue directory in the given queue group 8387 ** e -- envelope information for the item 8388 ** reason -- quarantine reason, NULL means unquarantine. 8389 ** 8390 ** Results: 8391 ** true if item changed, false otherwise 8392 ** 8393 ** Side Effects: 8394 ** Changes quarantine tag in queue file and renames it. 8395 */ 8396 8397 static bool 8398 quarantine_queue_item(qgrp, qdir, e, reason) 8399 int qgrp; 8400 int qdir; 8401 ENVELOPE *e; 8402 char *reason; 8403 { 8404 bool dirty = false; 8405 bool failing = false; 8406 bool foundq = false; 8407 bool finished = false; 8408 int fd; 8409 int flags; 8410 int oldtype; 8411 int newtype; 8412 int save_errno; 8413 MODE_T oldumask = 0; 8414 SM_FILE_T *oldqfp, *tempqfp; 8415 char *bp; 8416 char oldqf[MAXPATHLEN]; 8417 char tempqf[MAXPATHLEN]; 8418 char newqf[MAXPATHLEN]; 8419 char buf[MAXLINE]; 8420 8421 oldtype = queue_letter(e, ANYQFL_LETTER); 8422 (void) sm_strlcpy(oldqf, queuename(e, ANYQFL_LETTER), sizeof oldqf); 8423 (void) sm_strlcpy(tempqf, queuename(e, NEWQFL_LETTER), sizeof tempqf); 8424 8425 /* 8426 ** Instead of duplicating all the open 8427 ** and lock code here, tell readqf() to 8428 ** do that work and return the open 8429 ** file pointer in e_lockfp. Note that 8430 ** we must release the locks properly when 8431 ** we are done. 8432 */ 8433 8434 if (!readqf(e, true)) 8435 { 8436 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8437 "Skipping %s\n", qid_printname(e)); 8438 return false; 8439 } 8440 oldqfp = e->e_lockfp; 8441 8442 /* open the new queue file */ 8443 flags = O_CREAT|O_WRONLY|O_EXCL; 8444 if (bitset(S_IWGRP, QueueFileMode)) 8445 oldumask = umask(002); 8446 fd = open(tempqf, flags, QueueFileMode); 8447 if (bitset(S_IWGRP, QueueFileMode)) 8448 (void) umask(oldumask); 8449 RELEASE_QUEUE; 8450 8451 if (fd < 0) 8452 { 8453 save_errno = errno; 8454 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8455 "Skipping %s: Could not open %s: %s\n", 8456 qid_printname(e), tempqf, 8457 sm_errstring(save_errno)); 8458 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8459 return false; 8460 } 8461 if (!lockfile(fd, tempqf, NULL, LOCK_EX|LOCK_NB)) 8462 { 8463 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8464 "Skipping %s: Could not lock %s\n", 8465 qid_printname(e), tempqf); 8466 (void) close(fd); 8467 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8468 return false; 8469 } 8470 8471 tempqfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, (void *) &fd, 8472 SM_IO_WRONLY_B, NULL); 8473 if (tempqfp == NULL) 8474 { 8475 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8476 "Skipping %s: Could not lock %s\n", 8477 qid_printname(e), tempqf); 8478 (void) close(fd); 8479 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8480 return false; 8481 } 8482 8483 /* Copy the data over, changing the quarantine reason */ 8484 while ((bp = fgetfolded(buf, sizeof buf, oldqfp)) != NULL) 8485 { 8486 if (tTd(40, 4)) 8487 sm_dprintf("+++++ %s\n", bp); 8488 switch (bp[0]) 8489 { 8490 case 'q': /* quarantine reason */ 8491 foundq = true; 8492 if (reason == NULL) 8493 { 8494 if (Verbose) 8495 { 8496 (void) sm_io_fprintf(smioout, 8497 SM_TIME_DEFAULT, 8498 "%s: Removed quarantine of \"%s\"\n", 8499 e->e_id, &bp[1]); 8500 } 8501 sm_syslog(LOG_INFO, e->e_id, "unquarantine"); 8502 dirty = true; 8503 continue; 8504 } 8505 else if (strcmp(reason, &bp[1]) == 0) 8506 { 8507 if (Verbose) 8508 { 8509 (void) sm_io_fprintf(smioout, 8510 SM_TIME_DEFAULT, 8511 "%s: Already quarantined with \"%s\"\n", 8512 e->e_id, reason); 8513 } 8514 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8515 "q%s\n", reason); 8516 } 8517 else 8518 { 8519 if (Verbose) 8520 { 8521 (void) sm_io_fprintf(smioout, 8522 SM_TIME_DEFAULT, 8523 "%s: Quarantine changed from \"%s\" to \"%s\"\n", 8524 e->e_id, &bp[1], 8525 reason); 8526 } 8527 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8528 "q%s\n", reason); 8529 sm_syslog(LOG_INFO, e->e_id, "quarantine=%s", 8530 reason); 8531 dirty = true; 8532 } 8533 break; 8534 8535 case 'S': 8536 /* 8537 ** If we are quarantining an unquarantined item, 8538 ** need to put in a new 'q' line before it's 8539 ** too late. 8540 */ 8541 8542 if (!foundq && reason != NULL) 8543 { 8544 if (Verbose) 8545 { 8546 (void) sm_io_fprintf(smioout, 8547 SM_TIME_DEFAULT, 8548 "%s: Quarantined with \"%s\"\n", 8549 e->e_id, reason); 8550 } 8551 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8552 "q%s\n", reason); 8553 sm_syslog(LOG_INFO, e->e_id, "quarantine=%s", 8554 reason); 8555 foundq = true; 8556 dirty = true; 8557 } 8558 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 case '.': 8565 finished = true; 8566 /* FALLTHROUGH */ 8567 8568 default: 8569 /* Copy the line to the new file */ 8570 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8571 "%s\n", bp); 8572 break; 8573 } 8574 } 8575 8576 /* Make sure we read the whole old file */ 8577 errno = sm_io_error(tempqfp); 8578 if (errno != 0 && errno != SM_IO_EOF) 8579 { 8580 save_errno = errno; 8581 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8582 "Skipping %s: Error reading %s: %s\n", 8583 qid_printname(e), oldqf, 8584 sm_errstring(save_errno)); 8585 failing = true; 8586 } 8587 8588 if (!failing && !finished) 8589 { 8590 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8591 "Skipping %s: Incomplete file: %s\n", 8592 qid_printname(e), oldqf); 8593 failing = true; 8594 } 8595 8596 /* Check if we actually changed anything or we can just bail now */ 8597 if (!dirty) 8598 { 8599 /* pretend we failed, even though we technically didn't */ 8600 failing = true; 8601 } 8602 8603 /* Make sure we wrote things out safely */ 8604 if (!failing && 8605 (sm_io_flush(tempqfp, SM_TIME_DEFAULT) != 0 || 8606 ((SuperSafe == SAFE_REALLY || 8607 SuperSafe == SAFE_REALLY_POSTMILTER || 8608 SuperSafe == SAFE_INTERACTIVE) && 8609 fsync(sm_io_getinfo(tempqfp, SM_IO_WHAT_FD, NULL)) < 0) || 8610 ((errno = sm_io_error(tempqfp)) != 0))) 8611 { 8612 save_errno = errno; 8613 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8614 "Skipping %s: Error writing %s: %s\n", 8615 qid_printname(e), tempqf, 8616 sm_errstring(save_errno)); 8617 failing = true; 8618 } 8619 8620 8621 /* Figure out the new filename */ 8622 newtype = (reason == NULL ? NORMQF_LETTER : QUARQF_LETTER); 8623 if (oldtype == newtype) 8624 { 8625 /* going to rename tempqf to oldqf */ 8626 (void) sm_strlcpy(newqf, oldqf, sizeof newqf); 8627 } 8628 else 8629 { 8630 /* going to rename tempqf to new name based on newtype */ 8631 (void) sm_strlcpy(newqf, queuename(e, newtype), sizeof newqf); 8632 } 8633 8634 save_errno = 0; 8635 8636 /* rename tempqf to newqf */ 8637 if (!failing && 8638 rename(tempqf, newqf) < 0) 8639 save_errno = (errno == 0) ? EINVAL : errno; 8640 8641 /* Check rename() success */ 8642 if (!failing && save_errno != 0) 8643 { 8644 sm_syslog(LOG_DEBUG, e->e_id, 8645 "quarantine_queue_item: rename(%s, %s): %s", 8646 tempqf, newqf, sm_errstring(save_errno)); 8647 8648 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8649 "Error renaming %s to %s: %s\n", 8650 tempqf, newqf, 8651 sm_errstring(save_errno)); 8652 if (oldtype == newtype) 8653 { 8654 /* 8655 ** Bail here since we don't know the state of 8656 ** the filesystem and may need to keep tempqf 8657 ** for the user to rescue us. 8658 */ 8659 8660 RELEASE_QUEUE; 8661 errno = save_errno; 8662 syserr("!452 Error renaming control file %s", tempqf); 8663 /* NOTREACHED */ 8664 } 8665 else 8666 { 8667 /* remove new file (if rename() half completed) */ 8668 if (xunlink(newqf) < 0) 8669 { 8670 save_errno = errno; 8671 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8672 "Error removing %s: %s\n", 8673 newqf, 8674 sm_errstring(save_errno)); 8675 } 8676 8677 /* tempqf removed below */ 8678 failing = true; 8679 } 8680 8681 } 8682 8683 /* If changing file types, need to remove old type */ 8684 if (!failing && oldtype != newtype) 8685 { 8686 if (xunlink(oldqf) < 0) 8687 { 8688 save_errno = errno; 8689 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8690 "Error removing %s: %s\n", 8691 oldqf, sm_errstring(save_errno)); 8692 } 8693 } 8694 8695 /* see if anything above failed */ 8696 if (failing) 8697 { 8698 /* Something failed: remove new file, old file still there */ 8699 (void) xunlink(tempqf); 8700 } 8701 8702 /* 8703 ** fsync() after file operations to make sure metadata is 8704 ** written to disk on filesystems in which renames are 8705 ** not guaranteed. It's ok if they fail, mail won't be lost. 8706 */ 8707 8708 if (SuperSafe != SAFE_NO) 8709 { 8710 /* for soft-updates */ 8711 (void) fsync(sm_io_getinfo(tempqfp, 8712 SM_IO_WHAT_FD, NULL)); 8713 8714 if (!failing) 8715 { 8716 /* for soft-updates */ 8717 (void) fsync(sm_io_getinfo(oldqfp, 8718 SM_IO_WHAT_FD, NULL)); 8719 } 8720 8721 /* for other odd filesystems */ 8722 SYNC_DIR(tempqf, false); 8723 } 8724 8725 /* Close up shop */ 8726 RELEASE_QUEUE; 8727 if (tempqfp != NULL) 8728 (void) sm_io_close(tempqfp, SM_TIME_DEFAULT); 8729 if (oldqfp != NULL) 8730 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8731 8732 /* All went well */ 8733 return !failing; 8734 } 8735 8736 /* 8737 ** QUARANTINE_QUEUE -- {un,}quarantine matching items in the queue 8738 ** 8739 ** Read all matching queue items, add/remove quarantine 8740 ** reason, and requeue appropriately. 8741 ** 8742 ** Parameters: 8743 ** reason -- quarantine reason, "." means unquarantine. 8744 ** qgrplimit -- limit to single queue group unless NOQGRP 8745 ** 8746 ** Results: 8747 ** none. 8748 ** 8749 ** Side Effects: 8750 ** Lots of changes to the queue. 8751 */ 8752 8753 void 8754 quarantine_queue(reason, qgrplimit) 8755 char *reason; 8756 int qgrplimit; 8757 { 8758 int changed = 0; 8759 int qgrp; 8760 8761 /* Convert internal representation of unquarantine */ 8762 if (reason != NULL && reason[0] == '.' && reason[1] == '\0') 8763 reason = NULL; 8764 8765 if (reason != NULL) 8766 { 8767 /* clean it */ 8768 reason = newstr(denlstring(reason, true, true)); 8769 } 8770 8771 for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++) 8772 { 8773 int qdir; 8774 8775 if (qgrplimit != NOQGRP && qgrplimit != qgrp) 8776 continue; 8777 8778 for (qdir = 0; qdir < Queue[qgrp]->qg_numqueues; qdir++) 8779 { 8780 int i; 8781 int nrequests; 8782 8783 if (StopRequest) 8784 stop_sendmail(); 8785 8786 nrequests = gatherq(qgrp, qdir, true, NULL, NULL); 8787 8788 /* first see if there is anything */ 8789 if (nrequests <= 0) 8790 { 8791 if (Verbose) 8792 { 8793 (void) sm_io_fprintf(smioout, 8794 SM_TIME_DEFAULT, "%s: no matches\n", 8795 qid_printqueue(qgrp, qdir)); 8796 } 8797 continue; 8798 } 8799 8800 if (Verbose) 8801 { 8802 (void) sm_io_fprintf(smioout, 8803 SM_TIME_DEFAULT, "Processing %s:\n", 8804 qid_printqueue(qgrp, qdir)); 8805 } 8806 8807 for (i = 0; i < WorkListCount; i++) 8808 { 8809 ENVELOPE e; 8810 8811 if (StopRequest) 8812 stop_sendmail(); 8813 8814 /* setup envelope */ 8815 clearenvelope(&e, true, sm_rpool_new_x(NULL)); 8816 e.e_id = WorkList[i].w_name + 2; 8817 e.e_qgrp = qgrp; 8818 e.e_qdir = qdir; 8819 8820 if (tTd(70, 101)) 8821 { 8822 sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8823 "Would do %s\n", e.e_id); 8824 changed++; 8825 } 8826 else if (quarantine_queue_item(qgrp, qdir, 8827 &e, reason)) 8828 changed++; 8829 8830 /* clean up */ 8831 sm_rpool_free(e.e_rpool); 8832 e.e_rpool = NULL; 8833 } 8834 if (WorkList != NULL) 8835 sm_free(WorkList); /* XXX */ 8836 WorkList = NULL; 8837 WorkListSize = 0; 8838 WorkListCount = 0; 8839 } 8840 } 8841 if (Verbose) 8842 { 8843 if (changed == 0) 8844 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8845 "No changes\n"); 8846 else 8847 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8848 "%d change%s\n", 8849 changed, 8850 changed == 1 ? "" : "s"); 8851 } 8852 } 8853