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