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