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