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