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