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