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