1 /* 2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * By using this file, you agree to the terms and conditions set 8 * forth in the LICENSE file which can be found at the top level of 9 * the sendmail distribution. 10 * 11 */ 12 13 # include "sendmail.h" 14 15 #ifndef lint 16 #if QUEUE 17 static char sccsid[] = "@(#)queue.c 8.211 (Berkeley) 1/25/1999 (with queueing)"; 18 #else 19 static char sccsid[] = "@(#)queue.c 8.211 (Berkeley) 1/25/1999 (without queueing)"; 20 #endif 21 #endif /* not lint */ 22 23 # include <errno.h> 24 # include <dirent.h> 25 26 # if QUEUE 27 28 /* 29 ** Work queue. 30 */ 31 32 struct work 33 { 34 char *w_name; /* name of control file */ 35 char *w_host; /* name of recipient host */ 36 bool w_lock; /* is message locked? */ 37 bool w_tooyoung; /* is it too young to run? */ 38 long w_pri; /* priority of message, see below */ 39 time_t w_ctime; /* creation time of message */ 40 struct work *w_next; /* next in queue */ 41 }; 42 43 typedef struct work WORK; 44 45 WORK *WorkQ; /* queue of things to be done */ 46 47 #define QF_VERSION 2 /* version number of this queue format */ 48 49 extern int orderq __P((bool)); 50 /* 51 ** QUEUEUP -- queue a message up for future transmission. 52 ** 53 ** Parameters: 54 ** e -- the envelope to queue up. 55 ** announce -- if TRUE, tell when you are queueing up. 56 ** 57 ** Returns: 58 ** none. 59 ** 60 ** Side Effects: 61 ** The current request are saved in a control file. 62 ** The queue file is left locked. 63 */ 64 65 void 66 queueup(e, announce) 67 register ENVELOPE *e; 68 bool announce; 69 { 70 char *qf; 71 register FILE *tfp; 72 register HDR *h; 73 register ADDRESS *q; 74 int fd; 75 int i; 76 bool newid; 77 register char *p; 78 MAILER nullmailer; 79 MCI mcibuf; 80 char tf[MAXQFNAME]; 81 char buf[MAXLINE]; 82 extern void printctladdr __P((ADDRESS *, FILE *)); 83 84 /* 85 ** Create control file. 86 */ 87 88 newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags); 89 90 /* if newid, queuename will create a locked qf file in e->lockfp */ 91 strcpy(tf, queuename(e, 't')); 92 tfp = e->e_lockfp; 93 if (tfp == NULL) 94 newid = FALSE; 95 96 /* if newid, just write the qf file directly (instead of tf file) */ 97 if (!newid) 98 { 99 /* get a locked tf file */ 100 for (i = 0; i < 128; i++) 101 { 102 fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode); 103 if (fd < 0) 104 { 105 if (errno != EEXIST) 106 break; 107 if (LogLevel > 0 && (i % 32) == 0) 108 sm_syslog(LOG_ALERT, e->e_id, 109 "queueup: cannot create %s, uid=%d: %s", 110 tf, geteuid(), errstring(errno)); 111 } 112 else 113 { 114 if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB)) 115 break; 116 else if (LogLevel > 0 && (i % 32) == 0) 117 sm_syslog(LOG_ALERT, e->e_id, 118 "queueup: cannot lock %s: %s", 119 tf, errstring(errno)); 120 close(fd); 121 } 122 123 if ((i % 32) == 31) 124 { 125 /* save the old temp file away */ 126 (void) rename(tf, queuename(e, 'T')); 127 } 128 else 129 sleep(i % 32); 130 } 131 if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL) 132 { 133 printopenfds(TRUE); 134 syserr("!queueup: cannot create queue temp file %s, uid=%d", 135 tf, geteuid()); 136 } 137 } 138 139 if (tTd(40, 1)) 140 printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id, 141 newid ? " (new id)" : ""); 142 if (tTd(40, 3)) 143 { 144 extern void printenvflags __P((ENVELOPE *)); 145 146 printf(" e_flags="); 147 printenvflags(e); 148 } 149 if (tTd(40, 32)) 150 { 151 printf(" sendq="); 152 printaddr(e->e_sendqueue, TRUE); 153 } 154 if (tTd(40, 9)) 155 { 156 printf(" tfp="); 157 dumpfd(fileno(tfp), TRUE, FALSE); 158 printf(" lockfp="); 159 if (e->e_lockfp == NULL) 160 printf("NULL\n"); 161 else 162 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 163 } 164 165 /* 166 ** If there is no data file yet, create one. 167 */ 168 169 if (!bitset(EF_HAS_DF, e->e_flags)) 170 { 171 register FILE *dfp = NULL; 172 char dfname[MAXQFNAME]; 173 struct stat stbuf; 174 175 strcpy(dfname, queuename(e, 'd')); 176 fd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode); 177 if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL) 178 syserr("!queueup: cannot create data temp file %s, uid=%d", 179 dfname, geteuid()); 180 if (fstat(fd, &stbuf) < 0) 181 e->e_dfino = -1; 182 else 183 { 184 e->e_dfdev = stbuf.st_dev; 185 e->e_dfino = stbuf.st_ino; 186 } 187 e->e_flags |= EF_HAS_DF; 188 bzero(&mcibuf, sizeof mcibuf); 189 mcibuf.mci_out = dfp; 190 mcibuf.mci_mailer = FileMailer; 191 (*e->e_putbody)(&mcibuf, e, NULL); 192 (void) xfclose(dfp, "queueup dfp", e->e_id); 193 e->e_putbody = putbody; 194 } 195 196 /* 197 ** Output future work requests. 198 ** Priority and creation time should be first, since 199 ** they are required by orderq. 200 */ 201 202 /* output queue version number (must be first!) */ 203 fprintf(tfp, "V%d\n", QF_VERSION); 204 205 /* output creation time */ 206 fprintf(tfp, "T%ld\n", (long) e->e_ctime); 207 208 /* output last delivery time */ 209 fprintf(tfp, "K%ld\n", (long) e->e_dtime); 210 211 /* output number of delivery attempts */ 212 fprintf(tfp, "N%d\n", e->e_ntries); 213 214 /* output message priority */ 215 fprintf(tfp, "P%ld\n", e->e_msgpriority); 216 217 /* output inode number of data file */ 218 /* XXX should probably include device major/minor too */ 219 if (e->e_dfino != -1) 220 { 221 if (sizeof e->e_dfino > sizeof(long)) 222 fprintf(tfp, "I%d/%d/%s\n", 223 major(e->e_dfdev), minor(e->e_dfdev), 224 quad_to_string(e->e_dfino)); 225 else 226 fprintf(tfp, "I%d/%d/%lu\n", 227 major(e->e_dfdev), minor(e->e_dfdev), 228 (unsigned long) e->e_dfino); 229 } 230 231 /* output body type */ 232 if (e->e_bodytype != NULL) 233 fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE)); 234 235 #if _FFR_SAVE_CHARSET 236 if (e->e_charset != NULL) 237 fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE)); 238 #endif 239 240 /* message from envelope, if it exists */ 241 if (e->e_message != NULL) 242 fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE)); 243 244 /* send various flag bits through */ 245 p = buf; 246 if (bitset(EF_WARNING, e->e_flags)) 247 *p++ = 'w'; 248 if (bitset(EF_RESPONSE, e->e_flags)) 249 *p++ = 'r'; 250 if (bitset(EF_HAS8BIT, e->e_flags)) 251 *p++ = '8'; 252 if (bitset(EF_DELETE_BCC, e->e_flags)) 253 *p++ = 'b'; 254 if (bitset(EF_RET_PARAM, e->e_flags)) 255 *p++ = 'd'; 256 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 257 *p++ = 'n'; 258 *p++ = '\0'; 259 if (buf[0] != '\0') 260 fprintf(tfp, "F%s\n", buf); 261 262 /* $r and $s and $_ macro values */ 263 if ((p = macvalue('r', e)) != NULL) 264 fprintf(tfp, "$r%s\n", denlstring(p, TRUE, FALSE)); 265 if ((p = macvalue('s', e)) != NULL) 266 fprintf(tfp, "$s%s\n", denlstring(p, TRUE, FALSE)); 267 if ((p = macvalue('_', e)) != NULL) 268 fprintf(tfp, "$_%s\n", denlstring(p, TRUE, FALSE)); 269 270 /* output name of sender */ 271 if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) 272 p = e->e_sender; 273 else 274 p = e->e_from.q_paddr; 275 fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE)); 276 277 /* output ESMTP-supplied "original" information */ 278 if (e->e_envid != NULL) 279 fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE)); 280 281 /* output list of recipient addresses */ 282 printctladdr(NULL, NULL); 283 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 284 { 285 if (bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags)) 286 { 287 #if XDEBUG 288 if (bitset(QQUEUEUP, q->q_flags)) 289 sm_syslog(LOG_DEBUG, e->e_id, 290 "dropenvelope: q_flags = %x, paddr = %s", 291 q->q_flags, q->q_paddr); 292 #endif 293 continue; 294 } 295 printctladdr(q, tfp); 296 if (q->q_orcpt != NULL) 297 fprintf(tfp, "Q%s\n", 298 denlstring(q->q_orcpt, TRUE, FALSE)); 299 putc('R', tfp); 300 if (bitset(QPRIMARY, q->q_flags)) 301 putc('P', tfp); 302 if (bitset(QHASNOTIFY, q->q_flags)) 303 putc('N', tfp); 304 if (bitset(QPINGONSUCCESS, q->q_flags)) 305 putc('S', tfp); 306 if (bitset(QPINGONFAILURE, q->q_flags)) 307 putc('F', tfp); 308 if (bitset(QPINGONDELAY, q->q_flags)) 309 putc('D', tfp); 310 putc(':', tfp); 311 fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE)); 312 if (announce) 313 { 314 e->e_to = q->q_paddr; 315 message("queued"); 316 if (LogLevel > 8) 317 logdelivery(q->q_mailer, NULL, "queued", 318 NULL, (time_t) 0, e); 319 e->e_to = NULL; 320 } 321 if (tTd(40, 1)) 322 { 323 printf("queueing "); 324 printaddr(q, FALSE); 325 } 326 } 327 328 /* 329 ** Output headers for this message. 330 ** Expand macros completely here. Queue run will deal with 331 ** everything as absolute headers. 332 ** All headers that must be relative to the recipient 333 ** can be cracked later. 334 ** We set up a "null mailer" -- i.e., a mailer that will have 335 ** no effect on the addresses as they are output. 336 */ 337 338 bzero((char *) &nullmailer, sizeof nullmailer); 339 nullmailer.m_re_rwset = nullmailer.m_rh_rwset = 340 nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1; 341 nullmailer.m_eol = "\n"; 342 bzero(&mcibuf, sizeof mcibuf); 343 mcibuf.mci_mailer = &nullmailer; 344 mcibuf.mci_out = tfp; 345 346 define('g', "\201f", e); 347 for (h = e->e_header; h != NULL; h = h->h_link) 348 { 349 extern bool bitzerop __P((BITMAP)); 350 351 if (h->h_value == NULL) 352 continue; 353 354 /* don't output resent headers on non-resent messages */ 355 if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) 356 continue; 357 358 /* expand macros; if null, don't output header at all */ 359 if (bitset(H_DEFAULT, h->h_flags)) 360 { 361 (void) expand(h->h_value, buf, sizeof buf, e); 362 if (buf[0] == '\0') 363 continue; 364 } 365 366 /* output this header */ 367 fprintf(tfp, "H"); 368 369 /* if conditional, output the set of conditions */ 370 if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags)) 371 { 372 int j; 373 374 (void) putc('?', tfp); 375 for (j = '\0'; j <= '\177'; j++) 376 if (bitnset(j, h->h_mflags)) 377 (void) putc(j, tfp); 378 (void) putc('?', tfp); 379 } 380 381 /* output the header: expand macros, convert addresses */ 382 if (bitset(H_DEFAULT, h->h_flags)) 383 { 384 fprintf(tfp, "%s: %s\n", 385 h->h_field, 386 denlstring(buf, FALSE, TRUE)); 387 } 388 else if (bitset(H_FROM|H_RCPT, h->h_flags)) 389 { 390 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 391 FILE *savetrace = TrafficLogFile; 392 393 TrafficLogFile = NULL; 394 395 if (bitset(H_FROM, h->h_flags)) 396 oldstyle = FALSE; 397 398 commaize(h, h->h_value, oldstyle, &mcibuf, e); 399 400 TrafficLogFile = savetrace; 401 } 402 else 403 { 404 fprintf(tfp, "%s: %s\n", 405 h->h_field, 406 denlstring(h->h_value, FALSE, TRUE)); 407 } 408 } 409 410 /* 411 ** Clean up. 412 ** 413 ** Write a terminator record -- this is to prevent 414 ** scurrilous crackers from appending any data. 415 */ 416 417 fprintf(tfp, ".\n"); 418 419 if (fflush(tfp) < 0 || 420 (SuperSafe && fsync(fileno(tfp)) < 0) || 421 ferror(tfp)) 422 { 423 if (newid) 424 syserr("!552 Error writing control file %s", tf); 425 else 426 syserr("!452 Error writing control file %s", tf); 427 } 428 429 if (!newid) 430 { 431 /* rename (locked) tf to be (locked) qf */ 432 qf = queuename(e, 'q'); 433 if (rename(tf, qf) < 0) 434 syserr("cannot rename(%s, %s), uid=%d", 435 tf, qf, geteuid()); 436 437 /* close and unlock old (locked) qf */ 438 if (e->e_lockfp != NULL) 439 (void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id); 440 e->e_lockfp = tfp; 441 } 442 else 443 qf = tf; 444 errno = 0; 445 e->e_flags |= EF_INQUEUE; 446 447 /* save log info */ 448 if (LogLevel > 79) 449 sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf); 450 451 if (tTd(40, 1)) 452 printf("<<<<< done queueing %s <<<<<\n\n", e->e_id); 453 return; 454 } 455 456 void 457 printctladdr(a, tfp) 458 register ADDRESS *a; 459 FILE *tfp; 460 { 461 char *uname; 462 register ADDRESS *q; 463 uid_t uid; 464 gid_t gid; 465 static ADDRESS *lastctladdr = NULL; 466 static uid_t lastuid; 467 468 /* initialization */ 469 if (a == NULL || a->q_alias == NULL || tfp == NULL) 470 { 471 if (lastctladdr != NULL && tfp != NULL) 472 fprintf(tfp, "C\n"); 473 lastctladdr = NULL; 474 lastuid = 0; 475 return; 476 } 477 478 /* find the active uid */ 479 q = getctladdr(a); 480 if (q == NULL) 481 { 482 uname = NULL; 483 uid = 0; 484 gid = 0; 485 } 486 else 487 { 488 uname = q->q_ruser != NULL ? q->q_ruser : q->q_user; 489 uid = q->q_uid; 490 gid = q->q_gid; 491 } 492 a = a->q_alias; 493 494 /* check to see if this is the same as last time */ 495 if (lastctladdr != NULL && uid == lastuid && 496 strcmp(lastctladdr->q_paddr, a->q_paddr) == 0) 497 return; 498 lastuid = uid; 499 lastctladdr = a; 500 501 if (uid == 0 || uname == NULL || uname[0] == '\0') 502 fprintf(tfp, "C"); 503 else 504 fprintf(tfp, "C%s:%ld:%ld", 505 denlstring(uname, TRUE, FALSE), (long) uid, (long) gid); 506 fprintf(tfp, ":%s\n", denlstring(a->q_paddr, TRUE, FALSE)); 507 } 508 /* 509 ** RUNQUEUE -- run the jobs in the queue. 510 ** 511 ** Gets the stuff out of the queue in some presumably logical 512 ** order and processes them. 513 ** 514 ** Parameters: 515 ** forkflag -- TRUE if the queue scanning should be done in 516 ** a child process. We double-fork so it is not our 517 ** child and we don't have to clean up after it. 518 ** verbose -- if TRUE, print out status information. 519 ** 520 ** Returns: 521 ** TRUE if the queue run successfully began. 522 ** 523 ** Side Effects: 524 ** runs things in the mail queue. 525 */ 526 527 ENVELOPE QueueEnvelope; /* the queue run envelope */ 528 extern int get_num_procs_online __P((void)); 529 530 bool 531 runqueue(forkflag, verbose) 532 bool forkflag; 533 bool verbose; 534 { 535 register ENVELOPE *e; 536 int njobs; 537 int sequenceno = 0; 538 time_t current_la_time; 539 extern ENVELOPE BlankEnvelope; 540 extern void clrdaemon __P((void)); 541 extern void runqueueevent __P((void)); 542 543 DoQueueRun = FALSE; 544 545 /* 546 ** If no work will ever be selected, don't even bother reading 547 ** the queue. 548 */ 549 550 CurrentLA = getla(); /* get load average */ 551 current_la_time = curtime(); 552 553 if (shouldqueue(WkRecipFact, current_la_time)) 554 { 555 char *msg = "Skipping queue run -- load average too high"; 556 557 if (verbose) 558 message("458 %s\n", msg); 559 if (LogLevel > 8) 560 sm_syslog(LOG_INFO, NOQID, 561 "runqueue: %s", 562 msg); 563 if (forkflag && QueueIntvl != 0) 564 (void) setevent(QueueIntvl, runqueueevent, 0); 565 return FALSE; 566 } 567 568 /* 569 ** See if we already have too many children. 570 */ 571 572 if (forkflag && QueueIntvl != 0 && 573 MaxChildren > 0 && CurChildren >= MaxChildren) 574 { 575 (void) setevent(QueueIntvl, runqueueevent, 0); 576 return FALSE; 577 } 578 579 /* 580 ** See if we want to go off and do other useful work. 581 */ 582 583 if (forkflag) 584 { 585 pid_t pid; 586 extern SIGFUNC_DECL intsig __P((int)); 587 extern SIGFUNC_DECL reapchild __P((int)); 588 589 blocksignal(SIGCHLD); 590 (void) setsignal(SIGCHLD, reapchild); 591 592 pid = dofork(); 593 if (pid == -1) 594 { 595 const char *msg = "Skipping queue run -- fork() failed"; 596 const char *err = errstring(errno); 597 598 if (verbose) 599 message("458 %s: %s\n", msg, err); 600 if (LogLevel > 8) 601 sm_syslog(LOG_INFO, NOQID, 602 "runqueue: %s: %s", 603 msg, err); 604 if (QueueIntvl != 0) 605 (void) setevent(QueueIntvl, runqueueevent, 0); 606 (void) releasesignal(SIGCHLD); 607 return FALSE; 608 } 609 if (pid != 0) 610 { 611 /* parent -- pick up intermediate zombie */ 612 (void) blocksignal(SIGALRM); 613 proc_list_add(pid, "Queue runner"); 614 (void) releasesignal(SIGALRM); 615 releasesignal(SIGCHLD); 616 if (QueueIntvl != 0) 617 (void) setevent(QueueIntvl, runqueueevent, 0); 618 return TRUE; 619 } 620 /* child -- double fork and clean up signals */ 621 clrcontrol(); 622 proc_list_clear(); 623 624 /* Add parent process as first child item */ 625 proc_list_add(getpid(), "Queue runner child process"); 626 releasesignal(SIGCHLD); 627 (void) setsignal(SIGCHLD, SIG_DFL); 628 (void) setsignal(SIGHUP, intsig); 629 } 630 631 sm_setproctitle(TRUE, "running queue: %s", QueueDir); 632 633 if (LogLevel > 69) 634 sm_syslog(LOG_DEBUG, NOQID, 635 "runqueue %s, pid=%d, forkflag=%d", 636 QueueDir, getpid(), forkflag); 637 638 /* 639 ** Release any resources used by the daemon code. 640 */ 641 642 # if DAEMON 643 clrdaemon(); 644 # endif /* DAEMON */ 645 646 /* force it to run expensive jobs */ 647 NoConnect = FALSE; 648 649 /* drop privileges */ 650 if (geteuid() == (uid_t) 0) 651 (void) drop_privileges(FALSE); 652 653 /* 654 ** Create ourselves an envelope 655 */ 656 657 CurEnv = &QueueEnvelope; 658 e = newenvelope(&QueueEnvelope, CurEnv); 659 e->e_flags = BlankEnvelope.e_flags; 660 661 /* make sure we have disconnected from parent */ 662 if (forkflag) 663 { 664 disconnect(1, e); 665 QuickAbort = FALSE; 666 } 667 668 /* 669 ** Make sure the alias database is open. 670 */ 671 672 initmaps(FALSE, e); 673 674 /* 675 ** If we are running part of the queue, always ignore stored 676 ** host status. 677 */ 678 679 if (QueueLimitId != NULL || QueueLimitSender != NULL || 680 QueueLimitRecipient != NULL) 681 { 682 IgnoreHostStatus = TRUE; 683 MinQueueAge = 0; 684 } 685 686 /* 687 ** Start making passes through the queue. 688 ** First, read and sort the entire queue. 689 ** Then, process the work in that order. 690 ** But if you take too long, start over. 691 */ 692 693 /* order the existing work requests */ 694 njobs = orderq(FALSE); 695 696 /* process them once at a time */ 697 while (WorkQ != NULL) 698 { 699 WORK *w = WorkQ; 700 701 WorkQ = WorkQ->w_next; 702 e->e_to = NULL; 703 704 /* 705 ** Ignore jobs that are too expensive for the moment. 706 ** 707 ** Get new load average every 30 seconds. 708 */ 709 710 if (current_la_time < curtime() - 30) 711 { 712 CurrentLA = getla(); 713 current_la_time = curtime(); 714 } 715 if (shouldqueue(WkRecipFact, current_la_time)) 716 { 717 char *msg = "Aborting queue run: load average too high"; 718 719 if (Verbose) 720 message("%s", msg); 721 if (LogLevel > 8) 722 sm_syslog(LOG_INFO, NOQID, 723 "runqueue: %s", 724 msg); 725 break; 726 } 727 sequenceno++; 728 if (shouldqueue(w->w_pri, w->w_ctime)) 729 { 730 if (Verbose) 731 message(""); 732 if (QueueSortOrder == QS_BYPRIORITY) 733 { 734 if (Verbose) 735 message("Skipping %s (sequence %d of %d) and flushing rest of queue", 736 w->w_name + 2, 737 sequenceno, 738 njobs); 739 if (LogLevel > 8) 740 sm_syslog(LOG_INFO, NOQID, 741 "runqueue: Flushing queue from %s (pri %ld, LA %d, %d of %d)", 742 w->w_name + 2, 743 w->w_pri, 744 CurrentLA, 745 sequenceno, 746 njobs); 747 break; 748 } 749 else if (Verbose) 750 message("Skipping %s (sequence %d of %d)", 751 w->w_name + 2, sequenceno, njobs); 752 } 753 else 754 { 755 pid_t pid; 756 757 if (Verbose) 758 { 759 message(""); 760 message("Running %s (sequence %d of %d)", 761 w->w_name + 2, sequenceno, njobs); 762 } 763 pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e); 764 errno = 0; 765 if (pid != 0) 766 (void) waitfor(pid); 767 } 768 free(w->w_name); 769 if (w->w_host) 770 free(w->w_host); 771 free((char *) w); 772 } 773 774 /* exit without the usual cleanup */ 775 e->e_id = NULL; 776 finis(TRUE, ExitStat); 777 /*NOTREACHED*/ 778 return TRUE; 779 } 780 781 782 /* 783 ** RUNQUEUEEVENT -- stub for use in setevent 784 */ 785 786 void 787 runqueueevent() 788 { 789 DoQueueRun = TRUE; 790 } 791 /* 792 ** ORDERQ -- order the work queue. 793 ** 794 ** Parameters: 795 ** doall -- if set, include everything in the queue (even 796 ** the jobs that cannot be run because the load 797 ** average is too high). Otherwise, exclude those 798 ** jobs. 799 ** 800 ** Returns: 801 ** The number of request in the queue (not necessarily 802 ** the number of requests in WorkQ however). 803 ** 804 ** Side Effects: 805 ** Sets WorkQ to the queue of available work, in order. 806 */ 807 808 # define NEED_P 001 809 # define NEED_T 002 810 # define NEED_R 004 811 # define NEED_S 010 812 813 static WORK *WorkList = NULL; 814 static int WorkListSize = 0; 815 816 int 817 orderq(doall) 818 bool doall; 819 { 820 register struct dirent *d; 821 register WORK *w; 822 register char *p; 823 DIR *f; 824 register int i; 825 int wn = -1; 826 int wc; 827 QUEUE_CHAR *check; 828 829 if (tTd(41, 1)) 830 { 831 printf("orderq:\n"); 832 833 check = QueueLimitId; 834 while (check != NULL) 835 { 836 printf("\tQueueLimitId = %s\n", 837 check->queue_match); 838 check = check->queue_next; 839 } 840 841 check = QueueLimitSender; 842 while (check != NULL) 843 { 844 printf("\tQueueLimitSender = %s\n", 845 check->queue_match); 846 check = check->queue_next; 847 } 848 849 check = QueueLimitRecipient; 850 while (check != NULL) 851 { 852 printf("\tQueueLimitRecipient = %s\n", 853 check->queue_match); 854 check = check->queue_next; 855 } 856 } 857 858 /* clear out old WorkQ */ 859 for (w = WorkQ; w != NULL; ) 860 { 861 register WORK *nw = w->w_next; 862 863 WorkQ = nw; 864 free(w->w_name); 865 if (w->w_host) 866 free(w->w_host); 867 free((char *) w); 868 w = nw; 869 } 870 871 /* open the queue directory */ 872 f = opendir("."); 873 if (f == NULL) 874 { 875 syserr("orderq: cannot open \"%s\" as \".\"", QueueDir); 876 return (0); 877 } 878 879 /* 880 ** Read the work directory. 881 */ 882 883 while ((d = readdir(f)) != NULL) 884 { 885 FILE *cf; 886 int qfver = 0; 887 char lbuf[MAXNAME + 1]; 888 extern bool strcontainedin __P((char *, char *)); 889 890 if (tTd(41, 50)) 891 printf("orderq: checking %s\n", d->d_name); 892 893 /* is this an interesting entry? */ 894 if (d->d_name[0] != 'q' || d->d_name[1] != 'f') 895 continue; 896 897 if (strlen(d->d_name) > MAXQFNAME) 898 { 899 if (Verbose) 900 printf("orderq: %s too long, %d max characters\n", 901 d->d_name, MAXQFNAME); 902 if (LogLevel > 0) 903 sm_syslog(LOG_ALERT, NOQID, 904 "orderq: %s too long, %d max characters", 905 d->d_name, MAXQFNAME); 906 continue; 907 } 908 909 check = QueueLimitId; 910 while (check != NULL) 911 { 912 if (strcontainedin(check->queue_match, d->d_name)) 913 break; 914 else 915 check = check->queue_next; 916 } 917 if (QueueLimitId != NULL && check == NULL) 918 continue; 919 920 #ifdef PICKY_QF_NAME_CHECK 921 /* 922 ** Check queue name for plausibility. This handles 923 ** both old and new type ids. 924 */ 925 926 p = d->d_name + 2; 927 if (isupper(p[0]) && isupper(p[2])) 928 p += 3; 929 else if (isupper(p[1])) 930 p += 2; 931 else 932 p = d->d_name; 933 for (i = 0; isdigit(*p); p++) 934 i++; 935 if (i < 5 || *p != '\0') 936 { 937 if (Verbose) 938 printf("orderq: bogus qf name %s\n", d->d_name); 939 if (LogLevel > 0) 940 sm_syslog(LOG_ALERT, NOQID, 941 "orderq: bogus qf name %s", 942 d->d_name); 943 if (strlen(d->d_name) > (SIZE_T) MAXNAME) 944 d->d_name[MAXNAME] = '\0'; 945 strcpy(lbuf, d->d_name); 946 lbuf[0] = 'Q'; 947 (void) rename(d->d_name, lbuf); 948 continue; 949 } 950 #endif 951 952 /* open control file (if not too many files) */ 953 if (++wn >= MaxQueueRun && MaxQueueRun > 0) 954 { 955 if (wn == MaxQueueRun && LogLevel > 0) 956 sm_syslog(LOG_ALERT, NOQID, 957 "WorkList for %s maxed out at %d", 958 QueueDir, MaxQueueRun); 959 continue; 960 } 961 if (wn >= WorkListSize) 962 { 963 extern void grow_wlist __P((void)); 964 965 grow_wlist(); 966 if (wn >= WorkListSize) 967 continue; 968 } 969 970 cf = fopen(d->d_name, "r"); 971 if (cf == NULL) 972 { 973 /* this may be some random person sending hir msgs */ 974 /* syserr("orderq: cannot open %s", cbuf); */ 975 if (tTd(41, 2)) 976 printf("orderq: cannot open %s: %s\n", 977 d->d_name, errstring(errno)); 978 errno = 0; 979 wn--; 980 continue; 981 } 982 w = &WorkList[wn]; 983 w->w_name = newstr(d->d_name); 984 w->w_host = NULL; 985 w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB); 986 w->w_tooyoung = FALSE; 987 988 /* make sure jobs in creation don't clog queue */ 989 w->w_pri = 0x7fffffff; 990 w->w_ctime = 0; 991 992 /* extract useful information */ 993 i = NEED_P | NEED_T; 994 if (QueueLimitSender != NULL) 995 i |= NEED_S; 996 if (QueueSortOrder == QS_BYHOST || QueueLimitRecipient != NULL) 997 i |= NEED_R; 998 while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) 999 { 1000 int c; 1001 time_t age; 1002 extern bool strcontainedin __P((char *, char *)); 1003 1004 p = strchr(lbuf, '\n'); 1005 if (p != NULL) 1006 *p = '\0'; 1007 else 1008 { 1009 /* flush rest of overly long line */ 1010 while ((c = getc(cf)) != EOF && c != '\n') 1011 continue; 1012 } 1013 1014 switch (lbuf[0]) 1015 { 1016 case 'V': 1017 qfver = atoi(&lbuf[1]); 1018 break; 1019 1020 case 'P': 1021 w->w_pri = atol(&lbuf[1]); 1022 i &= ~NEED_P; 1023 break; 1024 1025 case 'T': 1026 w->w_ctime = atol(&lbuf[1]); 1027 i &= ~NEED_T; 1028 break; 1029 1030 case 'R': 1031 if (w->w_host == NULL && 1032 (p = strrchr(&lbuf[1], '@')) != NULL) 1033 w->w_host = newstr(&p[1]); 1034 if (QueueLimitRecipient == NULL) 1035 { 1036 i &= ~NEED_R; 1037 break; 1038 } 1039 if (qfver > 0) 1040 { 1041 p = strchr(&lbuf[1], ':'); 1042 if (p == NULL) 1043 p = &lbuf[1]; 1044 } 1045 else 1046 p = &lbuf[1]; 1047 check = QueueLimitRecipient; 1048 while (check != NULL) 1049 { 1050 if (strcontainedin(check->queue_match, 1051 p)) 1052 break; 1053 else 1054 check = check->queue_next; 1055 } 1056 if (check != NULL) 1057 i &= ~NEED_R; 1058 break; 1059 1060 case 'S': 1061 check = QueueLimitSender; 1062 while (check != NULL) 1063 { 1064 if (strcontainedin(check->queue_match, 1065 &lbuf[1])) 1066 break; 1067 else 1068 check = check->queue_next; 1069 } 1070 if (check != NULL) 1071 i &= ~NEED_S; 1072 break; 1073 1074 case 'K': 1075 age = curtime() - (time_t) atol(&lbuf[1]); 1076 if (age >= 0 && MinQueueAge > 0 && 1077 age < MinQueueAge) 1078 w->w_tooyoung = TRUE; 1079 break; 1080 1081 case 'N': 1082 if (atol(&lbuf[1]) == 0) 1083 w->w_tooyoung = FALSE; 1084 break; 1085 } 1086 } 1087 (void) fclose(cf); 1088 1089 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 1090 bitset(NEED_R|NEED_S, i)) 1091 { 1092 /* don't even bother sorting this job in */ 1093 if (tTd(41, 49)) 1094 printf("skipping %s (%x)\n", w->w_name, i); 1095 free(w->w_name); 1096 if (w->w_host) 1097 free(w->w_host); 1098 wn--; 1099 } 1100 } 1101 (void) closedir(f); 1102 wn++; 1103 1104 wc = min(wn, WorkListSize); 1105 if (wc > MaxQueueRun && MaxQueueRun > 0) 1106 wc = MaxQueueRun; 1107 1108 if (QueueSortOrder == QS_BYHOST) 1109 { 1110 extern int workcmpf1(); 1111 extern int workcmpf2(); 1112 1113 /* 1114 ** Sort the work directory for the first time, 1115 ** based on host name, lock status, and priority. 1116 */ 1117 1118 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1); 1119 1120 /* 1121 ** If one message to host is locked, "lock" all messages 1122 ** to that host. 1123 */ 1124 1125 i = 0; 1126 while (i < wc) 1127 { 1128 if (!WorkList[i].w_lock) 1129 { 1130 i++; 1131 continue; 1132 } 1133 w = &WorkList[i]; 1134 while (++i < wc) 1135 { 1136 extern int sm_strcasecmp __P((char *, char *)); 1137 1138 if (WorkList[i].w_host == NULL && 1139 w->w_host == NULL) 1140 WorkList[i].w_lock = TRUE; 1141 else if (WorkList[i].w_host != NULL && 1142 w->w_host != NULL && 1143 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0) 1144 WorkList[i].w_lock = TRUE; 1145 else 1146 break; 1147 } 1148 } 1149 1150 /* 1151 ** Sort the work directory for the second time, 1152 ** based on lock status, host name, and priority. 1153 */ 1154 1155 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2); 1156 } 1157 else if (QueueSortOrder == QS_BYTIME) 1158 { 1159 extern int workcmpf3(); 1160 1161 /* 1162 ** Simple sort based on submission time only. 1163 */ 1164 1165 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3); 1166 } 1167 else 1168 { 1169 extern int workcmpf0(); 1170 1171 /* 1172 ** Simple sort based on queue priority only. 1173 */ 1174 1175 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0); 1176 } 1177 1178 /* 1179 ** Convert the work list into canonical form. 1180 ** Should be turning it into a list of envelopes here perhaps. 1181 */ 1182 1183 WorkQ = NULL; 1184 for (i = wc; --i >= 0; ) 1185 { 1186 w = (WORK *) xalloc(sizeof *w); 1187 w->w_name = WorkList[i].w_name; 1188 w->w_host = WorkList[i].w_host; 1189 w->w_lock = WorkList[i].w_lock; 1190 w->w_tooyoung = WorkList[i].w_tooyoung; 1191 w->w_pri = WorkList[i].w_pri; 1192 w->w_ctime = WorkList[i].w_ctime; 1193 w->w_next = WorkQ; 1194 WorkQ = w; 1195 } 1196 if (WorkList != NULL) 1197 free(WorkList); 1198 WorkList = NULL; 1199 WorkListSize = 0; 1200 1201 if (tTd(40, 1)) 1202 { 1203 for (w = WorkQ; w != NULL; w = w->w_next) 1204 printf("%32s: pri=%ld\n", w->w_name, w->w_pri); 1205 } 1206 1207 return (wn); 1208 } 1209 /* 1210 ** GROW_WLIST -- make the work list larger 1211 ** 1212 ** Parameters: 1213 ** none. 1214 ** 1215 ** Returns: 1216 ** none. 1217 ** 1218 ** Side Effects: 1219 ** Adds another QUEUESEGSIZE entries to WorkList if possible. 1220 ** It can fail if there isn't enough memory, so WorkListSize 1221 ** should be checked again upon return. 1222 */ 1223 1224 void 1225 grow_wlist() 1226 { 1227 if (tTd(41, 1)) 1228 printf("grow_wlist: WorkListSize=%d\n", WorkListSize); 1229 if (WorkList == NULL) 1230 { 1231 WorkList = (WORK *) xalloc(sizeof(WORK) * (QUEUESEGSIZE + 1)); 1232 WorkListSize = QUEUESEGSIZE; 1233 } 1234 else 1235 { 1236 int newsize = WorkListSize + QUEUESEGSIZE; 1237 WORK *newlist = (WORK *) realloc((char *)WorkList, 1238 (unsigned)sizeof(WORK) * (newsize + 1)); 1239 1240 if (newlist != NULL) 1241 { 1242 WorkListSize = newsize; 1243 WorkList = newlist; 1244 if (LogLevel > 1) 1245 { 1246 sm_syslog(LOG_NOTICE, NOQID, 1247 "grew WorkList for %s to %d", 1248 QueueDir, WorkListSize); 1249 } 1250 } 1251 else if (LogLevel > 0) 1252 { 1253 sm_syslog(LOG_ALERT, NOQID, 1254 "FAILED to grow WorkList for %s to %d", 1255 QueueDir, newsize); 1256 } 1257 } 1258 if (tTd(41, 1)) 1259 printf("grow_wlist: WorkListSize now %d\n", WorkListSize); 1260 } 1261 /* 1262 ** WORKCMPF0 -- simple priority-only compare function. 1263 ** 1264 ** Parameters: 1265 ** a -- the first argument. 1266 ** b -- the second argument. 1267 ** 1268 ** Returns: 1269 ** -1 if a < b 1270 ** 0 if a == b 1271 ** +1 if a > b 1272 ** 1273 ** Side Effects: 1274 ** none. 1275 */ 1276 1277 int 1278 workcmpf0(a, b) 1279 register WORK *a; 1280 register WORK *b; 1281 { 1282 long pa = a->w_pri; 1283 long pb = b->w_pri; 1284 1285 if (pa == pb) 1286 return 0; 1287 else if (pa > pb) 1288 return 1; 1289 else 1290 return -1; 1291 } 1292 /* 1293 ** WORKCMPF1 -- first compare function for ordering work based on host name. 1294 ** 1295 ** Sorts on host name, lock status, and priority in that order. 1296 ** 1297 ** Parameters: 1298 ** a -- the first argument. 1299 ** b -- the second argument. 1300 ** 1301 ** Returns: 1302 ** <0 if a < b 1303 ** 0 if a == b 1304 ** >0 if a > b 1305 ** 1306 ** Side Effects: 1307 ** none. 1308 */ 1309 1310 int 1311 workcmpf1(a, b) 1312 register WORK *a; 1313 register WORK *b; 1314 { 1315 int i; 1316 extern int sm_strcasecmp __P((char *, char *)); 1317 1318 /* host name */ 1319 if (a->w_host != NULL && b->w_host == NULL) 1320 return 1; 1321 else if (a->w_host == NULL && b->w_host != NULL) 1322 return -1; 1323 if (a->w_host != NULL && b->w_host != NULL && 1324 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1325 return i; 1326 1327 /* lock status */ 1328 if (a->w_lock != b->w_lock) 1329 return b->w_lock - a->w_lock; 1330 1331 /* job priority */ 1332 return a->w_pri - b->w_pri; 1333 } 1334 /* 1335 ** WORKCMPF2 -- second compare function for ordering work based on host name. 1336 ** 1337 ** Sorts on lock status, host name, and priority in that order. 1338 ** 1339 ** Parameters: 1340 ** a -- the first argument. 1341 ** b -- the second argument. 1342 ** 1343 ** Returns: 1344 ** <0 if a < b 1345 ** 0 if a == b 1346 ** >0 if a > b 1347 ** 1348 ** Side Effects: 1349 ** none. 1350 */ 1351 1352 int 1353 workcmpf2(a, b) 1354 register WORK *a; 1355 register WORK *b; 1356 { 1357 int i; 1358 extern int sm_strcasecmp __P((char *, char *)); 1359 1360 /* lock status */ 1361 if (a->w_lock != b->w_lock) 1362 return a->w_lock - b->w_lock; 1363 1364 /* host name */ 1365 if (a->w_host != NULL && b->w_host == NULL) 1366 return 1; 1367 else if (a->w_host == NULL && b->w_host != NULL) 1368 return -1; 1369 if (a->w_host != NULL && b->w_host != NULL && 1370 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1371 return i; 1372 1373 /* job priority */ 1374 return a->w_pri - b->w_pri; 1375 } 1376 /* 1377 ** WORKCMPF3 -- simple submission-time-only compare function. 1378 ** 1379 ** Parameters: 1380 ** a -- the first argument. 1381 ** b -- the second argument. 1382 ** 1383 ** Returns: 1384 ** -1 if a < b 1385 ** 0 if a == b 1386 ** +1 if a > b 1387 ** 1388 ** Side Effects: 1389 ** none. 1390 */ 1391 1392 int 1393 workcmpf3(a, b) 1394 register WORK *a; 1395 register WORK *b; 1396 { 1397 if (a->w_ctime > b->w_ctime) 1398 return 1; 1399 else if (a->w_ctime < b->w_ctime) 1400 return -1; 1401 else 1402 return 0; 1403 } 1404 /* 1405 ** DOWORK -- do a work request. 1406 ** 1407 ** Parameters: 1408 ** id -- the ID of the job to run. 1409 ** forkflag -- if set, run this in background. 1410 ** requeueflag -- if set, reinstantiate the queue quickly. 1411 ** This is used when expanding aliases in the queue. 1412 ** If forkflag is also set, it doesn't wait for the 1413 ** child. 1414 ** e - the envelope in which to run it. 1415 ** 1416 ** Returns: 1417 ** process id of process that is running the queue job. 1418 ** 1419 ** Side Effects: 1420 ** The work request is satisfied if possible. 1421 */ 1422 1423 pid_t 1424 dowork(id, forkflag, requeueflag, e) 1425 char *id; 1426 bool forkflag; 1427 bool requeueflag; 1428 register ENVELOPE *e; 1429 { 1430 register pid_t pid; 1431 extern bool readqf __P((ENVELOPE *)); 1432 1433 if (tTd(40, 1)) 1434 printf("dowork(%s)\n", id); 1435 1436 /* 1437 ** Fork for work. 1438 */ 1439 1440 if (forkflag) 1441 { 1442 pid = fork(); 1443 if (pid < 0) 1444 { 1445 syserr("dowork: cannot fork"); 1446 return 0; 1447 } 1448 else if (pid > 0) 1449 { 1450 /* parent -- clean out connection cache */ 1451 mci_flush(FALSE, NULL); 1452 } 1453 else 1454 { 1455 /* child -- error messages to the transcript */ 1456 QuickAbort = OnlyOneError = FALSE; 1457 1458 /* 1459 ** Since the delivery may happen in a child and the 1460 ** parent does not wait, the parent may close the 1461 ** maps thereby removing any shared memory used by 1462 ** the map. Therefore, open a copy of the maps for 1463 ** the delivery process. 1464 */ 1465 1466 initmaps(FALSE, e); 1467 } 1468 } 1469 else 1470 { 1471 pid = 0; 1472 } 1473 1474 if (pid == 0) 1475 { 1476 /* 1477 ** CHILD 1478 ** Lock the control file to avoid duplicate deliveries. 1479 ** Then run the file as though we had just read it. 1480 ** We save an idea of the temporary name so we 1481 ** can recover on interrupt. 1482 */ 1483 1484 /* set basic modes, etc. */ 1485 (void) alarm(0); 1486 clearenvelope(e, FALSE); 1487 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 1488 e->e_sendmode = SM_DELIVER; 1489 e->e_errormode = EM_MAIL; 1490 e->e_id = id; 1491 GrabTo = UseErrorsTo = FALSE; 1492 ExitStat = EX_OK; 1493 if (forkflag) 1494 { 1495 disconnect(1, e); 1496 OpMode = MD_DELIVER; 1497 } 1498 sm_setproctitle(TRUE, "%s: from queue", id); 1499 if (LogLevel > 76) 1500 sm_syslog(LOG_DEBUG, e->e_id, 1501 "dowork, pid=%d", 1502 getpid()); 1503 1504 /* don't use the headers from sendmail.cf... */ 1505 e->e_header = NULL; 1506 1507 /* read the queue control file -- return if locked */ 1508 if (!readqf(e)) 1509 { 1510 if (tTd(40, 4) && e->e_id != NULL) 1511 printf("readqf(%s) failed\n", e->e_id); 1512 e->e_id = NULL; 1513 if (forkflag) 1514 finis(FALSE, EX_OK); 1515 else 1516 return 0; 1517 } 1518 1519 e->e_flags |= EF_INQUEUE; 1520 eatheader(e, requeueflag); 1521 1522 if (requeueflag) 1523 queueup(e, FALSE); 1524 1525 /* do the delivery */ 1526 sendall(e, SM_DELIVER); 1527 1528 /* finish up and exit */ 1529 if (forkflag) 1530 finis(TRUE, ExitStat); 1531 else 1532 dropenvelope(e, TRUE); 1533 } 1534 e->e_id = NULL; 1535 return pid; 1536 } 1537 /* 1538 ** READQF -- read queue file and set up environment. 1539 ** 1540 ** Parameters: 1541 ** e -- the envelope of the job to run. 1542 ** 1543 ** Returns: 1544 ** TRUE if it successfully read the queue file. 1545 ** FALSE otherwise. 1546 ** 1547 ** Side Effects: 1548 ** The queue file is returned locked. 1549 */ 1550 1551 bool 1552 readqf(e) 1553 register ENVELOPE *e; 1554 { 1555 register FILE *qfp; 1556 ADDRESS *ctladdr; 1557 struct stat st; 1558 char *bp; 1559 int qfver = 0; 1560 long hdrsize = 0; 1561 register char *p; 1562 char *orcpt = NULL; 1563 bool nomore = FALSE; 1564 char qf[MAXQFNAME]; 1565 char buf[MAXLINE]; 1566 extern ADDRESS *setctluser __P((char *, int)); 1567 1568 /* 1569 ** Read and process the file. 1570 */ 1571 1572 strcpy(qf, queuename(e, 'q')); 1573 qfp = fopen(qf, "r+"); 1574 if (qfp == NULL) 1575 { 1576 if (tTd(40, 8)) 1577 printf("readqf(%s): fopen failure (%s)\n", 1578 qf, errstring(errno)); 1579 if (errno != ENOENT) 1580 syserr("readqf: no control file %s", qf); 1581 return FALSE; 1582 } 1583 1584 if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB)) 1585 { 1586 /* being processed by another queuer */ 1587 if (Verbose || tTd(40, 8)) 1588 printf("%s: locked\n", e->e_id); 1589 if (LogLevel > 19) 1590 sm_syslog(LOG_DEBUG, e->e_id, "locked"); 1591 (void) fclose(qfp); 1592 return FALSE; 1593 } 1594 1595 /* 1596 ** Check the queue file for plausibility to avoid attacks. 1597 */ 1598 1599 if (fstat(fileno(qfp), &st) < 0) 1600 { 1601 /* must have been being processed by someone else */ 1602 if (tTd(40, 8)) 1603 printf("readqf(%s): fstat failure (%s)\n", 1604 qf, errstring(errno)); 1605 fclose(qfp); 1606 return FALSE; 1607 } 1608 1609 if ((st.st_uid != geteuid() && geteuid() != RealUid) || 1610 bitset(S_IWOTH|S_IWGRP, st.st_mode)) 1611 { 1612 if (LogLevel > 0) 1613 { 1614 sm_syslog(LOG_ALERT, e->e_id, 1615 "bogus queue file, uid=%d, mode=%o", 1616 st.st_uid, st.st_mode); 1617 } 1618 if (tTd(40, 8)) 1619 printf("readqf(%s): bogus file\n", qf); 1620 loseqfile(e, "bogus file uid in mqueue"); 1621 fclose(qfp); 1622 return FALSE; 1623 } 1624 1625 if (st.st_size == 0) 1626 { 1627 /* must be a bogus file -- if also old, just remove it */ 1628 if (st.st_ctime + 10 * 60 < curtime()) 1629 { 1630 qf[0] = 'd'; 1631 (void) unlink(qf); 1632 qf[0] = 'q'; 1633 (void) unlink(qf); 1634 } 1635 fclose(qfp); 1636 return FALSE; 1637 } 1638 1639 if (st.st_nlink == 0) 1640 { 1641 /* 1642 ** Race condition -- we got a file just as it was being 1643 ** unlinked. Just assume it is zero length. 1644 */ 1645 1646 fclose(qfp); 1647 return FALSE; 1648 } 1649 1650 /* good file -- save this lock */ 1651 e->e_lockfp = qfp; 1652 1653 /* do basic system initialization */ 1654 initsys(e); 1655 define('i', e->e_id, e); 1656 1657 LineNumber = 0; 1658 e->e_flags |= EF_GLOBALERRS; 1659 OpMode = MD_DELIVER; 1660 ctladdr = NULL; 1661 e->e_dfino = -1; 1662 e->e_msgsize = -1; 1663 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 1664 { 1665 register char *p; 1666 u_long qflags; 1667 ADDRESS *q; 1668 int mid; 1669 auto char *ep; 1670 1671 if (tTd(40, 4)) 1672 printf("+++++ %s\n", bp); 1673 if (nomore) 1674 { 1675 /* hack attack */ 1676 syserr("SECURITY ALERT: extra data in qf: %s", bp); 1677 fclose(qfp); 1678 loseqfile(e, "bogus queue line"); 1679 return FALSE; 1680 } 1681 switch (bp[0]) 1682 { 1683 case 'V': /* queue file version number */ 1684 qfver = atoi(&bp[1]); 1685 if (qfver <= QF_VERSION) 1686 break; 1687 syserr("Version number in qf (%d) greater than max (%d)", 1688 qfver, QF_VERSION); 1689 fclose(qfp); 1690 loseqfile(e, "unsupported qf file version"); 1691 return FALSE; 1692 1693 case 'C': /* specify controlling user */ 1694 ctladdr = setctluser(&bp[1], qfver); 1695 break; 1696 1697 case 'Q': /* original recipient */ 1698 orcpt = newstr(&bp[1]); 1699 break; 1700 1701 case 'R': /* specify recipient */ 1702 p = bp; 1703 qflags = 0; 1704 if (qfver >= 1) 1705 { 1706 /* get flag bits */ 1707 while (*++p != '\0' && *p != ':') 1708 { 1709 switch (*p) 1710 { 1711 case 'N': 1712 qflags |= QHASNOTIFY; 1713 break; 1714 1715 case 'S': 1716 qflags |= QPINGONSUCCESS; 1717 break; 1718 1719 case 'F': 1720 qflags |= QPINGONFAILURE; 1721 break; 1722 1723 case 'D': 1724 qflags |= QPINGONDELAY; 1725 break; 1726 1727 case 'P': 1728 qflags |= QPRIMARY; 1729 break; 1730 } 1731 } 1732 } 1733 else 1734 qflags |= QPRIMARY; 1735 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e); 1736 if (q != NULL) 1737 { 1738 q->q_alias = ctladdr; 1739 if (qfver >= 1) 1740 q->q_flags &= ~Q_PINGFLAGS; 1741 q->q_flags |= qflags; 1742 q->q_orcpt = orcpt; 1743 (void) recipient(q, &e->e_sendqueue, 0, e); 1744 } 1745 orcpt = NULL; 1746 break; 1747 1748 case 'E': /* specify error recipient */ 1749 /* no longer used */ 1750 break; 1751 1752 case 'H': /* header */ 1753 (void) chompheader(&bp[1], FALSE, NULL, e); 1754 hdrsize += strlen(&bp[1]); 1755 break; 1756 1757 case 'L': /* Solaris Content-Length: */ 1758 case 'M': /* message */ 1759 /* ignore this; we want a new message next time */ 1760 break; 1761 1762 case 'S': /* sender */ 1763 setsender(newstr(&bp[1]), e, NULL, '\0', TRUE); 1764 break; 1765 1766 case 'B': /* body type */ 1767 e->e_bodytype = newstr(&bp[1]); 1768 break; 1769 1770 #if _FFR_SAVE_CHARSET 1771 case 'X': /* character set */ 1772 e->e_charset = newstr(&bp[1]); 1773 break; 1774 #endif 1775 1776 case 'D': /* data file name */ 1777 /* obsolete -- ignore */ 1778 break; 1779 1780 case 'T': /* init time */ 1781 e->e_ctime = atol(&bp[1]); 1782 break; 1783 1784 case 'I': /* data file's inode number */ 1785 /* regenerated below */ 1786 break; 1787 1788 case 'K': /* time of last deliver attempt */ 1789 e->e_dtime = atol(&buf[1]); 1790 break; 1791 1792 case 'N': /* number of delivery attempts */ 1793 e->e_ntries = atoi(&buf[1]); 1794 1795 /* if this has been tried recently, let it be */ 1796 if (e->e_ntries > 0 && 1797 MinQueueAge > 0 && e->e_dtime <= curtime() && 1798 curtime() < e->e_dtime + MinQueueAge) 1799 { 1800 char *howlong = pintvl(curtime() - e->e_dtime, TRUE); 1801 1802 if (Verbose || tTd(40, 8)) 1803 printf("%s: too young (%s)\n", 1804 e->e_id, howlong); 1805 if (LogLevel > 19) 1806 sm_syslog(LOG_DEBUG, e->e_id, 1807 "too young (%s)", 1808 howlong); 1809 e->e_id = NULL; 1810 unlockqueue(e); 1811 return FALSE; 1812 } 1813 break; 1814 1815 case 'P': /* message priority */ 1816 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 1817 break; 1818 1819 case 'F': /* flag bits */ 1820 if (strncmp(bp, "From ", 5) == 0) 1821 { 1822 /* we are being spoofed! */ 1823 syserr("SECURITY ALERT: bogus qf line %s", bp); 1824 fclose(qfp); 1825 loseqfile(e, "bogus queue line"); 1826 return FALSE; 1827 } 1828 for (p = &bp[1]; *p != '\0'; p++) 1829 { 1830 switch (*p) 1831 { 1832 case 'w': /* warning sent */ 1833 e->e_flags |= EF_WARNING; 1834 break; 1835 1836 case 'r': /* response */ 1837 e->e_flags |= EF_RESPONSE; 1838 break; 1839 1840 case '8': /* has 8 bit data */ 1841 e->e_flags |= EF_HAS8BIT; 1842 break; 1843 1844 case 'b': /* delete Bcc: header */ 1845 e->e_flags |= EF_DELETE_BCC; 1846 break; 1847 1848 case 'd': /* envelope has DSN RET= */ 1849 e->e_flags |= EF_RET_PARAM; 1850 break; 1851 1852 case 'n': /* don't return body */ 1853 e->e_flags |= EF_NO_BODY_RETN; 1854 break; 1855 } 1856 } 1857 break; 1858 1859 case 'Z': /* original envelope id from ESMTP */ 1860 e->e_envid = newstr(&bp[1]); 1861 break; 1862 1863 case '$': /* define macro */ 1864 mid = macid(&bp[1], &ep); 1865 define(mid, newstr(ep), e); 1866 break; 1867 1868 case '.': /* terminate file */ 1869 nomore = TRUE; 1870 break; 1871 1872 default: 1873 syserr("readqf: %s: line %d: bad line \"%s\"", 1874 qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); 1875 fclose(qfp); 1876 loseqfile(e, "unrecognized line"); 1877 return FALSE; 1878 } 1879 1880 if (bp != buf) 1881 free(bp); 1882 } 1883 1884 /* 1885 ** If we haven't read any lines, this queue file is empty. 1886 ** Arrange to remove it without referencing any null pointers. 1887 */ 1888 1889 if (LineNumber == 0) 1890 { 1891 errno = 0; 1892 e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; 1893 return TRUE; 1894 } 1895 1896 /* 1897 ** Arrange to read the data file. 1898 */ 1899 1900 p = queuename(e, 'd'); 1901 e->e_dfp = fopen(p, "r"); 1902 if (e->e_dfp == NULL) 1903 { 1904 syserr("readqf: cannot open %s", p); 1905 } 1906 else 1907 { 1908 e->e_flags |= EF_HAS_DF; 1909 if (fstat(fileno(e->e_dfp), &st) >= 0) 1910 { 1911 e->e_msgsize = st.st_size + hdrsize; 1912 e->e_dfdev = st.st_dev; 1913 e->e_dfino = st.st_ino; 1914 } 1915 } 1916 1917 return TRUE; 1918 } 1919 /* 1920 ** PRINTQUEUE -- print out a representation of the mail queue 1921 ** 1922 ** Parameters: 1923 ** none. 1924 ** 1925 ** Returns: 1926 ** none. 1927 ** 1928 ** Side Effects: 1929 ** Prints a listing of the mail queue on the standard output. 1930 */ 1931 1932 void 1933 printqueue() 1934 { 1935 register WORK *w; 1936 FILE *f; 1937 int nrequests; 1938 char buf[MAXLINE]; 1939 1940 /* 1941 ** Check for permission to print the queue 1942 */ 1943 1944 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 1945 { 1946 struct stat st; 1947 # ifdef NGROUPS_MAX 1948 int n; 1949 extern GIDSET_T InitialGidSet[NGROUPS_MAX]; 1950 # endif 1951 1952 if (stat(QueueDir, &st) < 0) 1953 { 1954 syserr("Cannot stat %s", QueueDir); 1955 return; 1956 } 1957 # ifdef NGROUPS_MAX 1958 n = NGROUPS_MAX; 1959 while (--n >= 0) 1960 { 1961 if (InitialGidSet[n] == st.st_gid) 1962 break; 1963 } 1964 if (n < 0 && RealGid != st.st_gid) 1965 # else 1966 if (RealGid != st.st_gid) 1967 # endif 1968 { 1969 usrerr("510 You are not permitted to see the queue"); 1970 setstat(EX_NOPERM); 1971 return; 1972 } 1973 } 1974 1975 /* 1976 ** Read and order the queue. 1977 */ 1978 1979 nrequests = orderq(TRUE); 1980 1981 /* 1982 ** Print the work list that we have read. 1983 */ 1984 1985 /* first see if there is anything */ 1986 if (nrequests <= 0) 1987 { 1988 printf("Mail queue is empty\n"); 1989 return; 1990 } 1991 1992 CurrentLA = getla(); /* get load average */ 1993 1994 printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s"); 1995 if (MaxQueueRun > 0 && nrequests > MaxQueueRun) 1996 printf(", only %d printed", MaxQueueRun); 1997 if (Verbose) 1998 printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n"); 1999 else 2000 printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); 2001 for (w = WorkQ; w != NULL; w = w->w_next) 2002 { 2003 struct stat st; 2004 auto time_t submittime = 0; 2005 long dfsize; 2006 int flags = 0; 2007 int qfver; 2008 char statmsg[MAXLINE]; 2009 char bodytype[MAXNAME + 1]; 2010 2011 printf("%8s", w->w_name + 2); 2012 f = fopen(w->w_name, "r"); 2013 if (f == NULL) 2014 { 2015 printf(" (job completed)\n"); 2016 errno = 0; 2017 continue; 2018 } 2019 w->w_name[0] = 'd'; 2020 if (stat(w->w_name, &st) >= 0) 2021 dfsize = st.st_size; 2022 else 2023 dfsize = -1; 2024 if (w->w_lock) 2025 printf("*"); 2026 else if (w->w_tooyoung) 2027 printf("-"); 2028 else if (shouldqueue(w->w_pri, w->w_ctime)) 2029 printf("X"); 2030 else 2031 printf(" "); 2032 errno = 0; 2033 2034 statmsg[0] = bodytype[0] = '\0'; 2035 qfver = 0; 2036 while (fgets(buf, sizeof buf, f) != NULL) 2037 { 2038 register int i; 2039 register char *p; 2040 2041 fixcrlf(buf, TRUE); 2042 switch (buf[0]) 2043 { 2044 case 'V': /* queue file version */ 2045 qfver = atoi(&buf[1]); 2046 break; 2047 2048 case 'M': /* error message */ 2049 if ((i = strlen(&buf[1])) >= sizeof statmsg) 2050 i = sizeof statmsg - 1; 2051 bcopy(&buf[1], statmsg, i); 2052 statmsg[i] = '\0'; 2053 break; 2054 2055 case 'B': /* body type */ 2056 if ((i = strlen(&buf[1])) >= sizeof bodytype) 2057 i = sizeof bodytype - 1; 2058 bcopy(&buf[1], bodytype, i); 2059 bodytype[i] = '\0'; 2060 break; 2061 2062 case 'S': /* sender name */ 2063 if (Verbose) 2064 printf("%8ld %10ld%c%.12s %.78s", 2065 dfsize, 2066 w->w_pri, 2067 bitset(EF_WARNING, flags) ? '+' : ' ', 2068 ctime(&submittime) + 4, 2069 &buf[1]); 2070 else 2071 printf("%8ld %.16s %.45s", dfsize, 2072 ctime(&submittime), &buf[1]); 2073 if (statmsg[0] != '\0' || bodytype[0] != '\0') 2074 { 2075 printf("\n %10.10s", bodytype); 2076 if (statmsg[0] != '\0') 2077 printf(" (%.*s)", 2078 Verbose ? 100 : 60, 2079 statmsg); 2080 } 2081 break; 2082 2083 case 'C': /* controlling user */ 2084 if (Verbose) 2085 printf("\n\t\t\t\t (---%.74s---)", 2086 &buf[1]); 2087 break; 2088 2089 case 'R': /* recipient name */ 2090 p = &buf[1]; 2091 if (qfver >= 1) 2092 { 2093 p = strchr(p, ':'); 2094 if (p == NULL) 2095 break; 2096 p++; 2097 } 2098 if (Verbose) 2099 printf("\n\t\t\t\t\t %.78s", p); 2100 else 2101 printf("\n\t\t\t\t %.45s", p); 2102 break; 2103 2104 case 'T': /* creation time */ 2105 submittime = atol(&buf[1]); 2106 break; 2107 2108 case 'F': /* flag bits */ 2109 for (p = &buf[1]; *p != '\0'; p++) 2110 { 2111 switch (*p) 2112 { 2113 case 'w': 2114 flags |= EF_WARNING; 2115 break; 2116 } 2117 } 2118 } 2119 } 2120 if (submittime == (time_t) 0) 2121 printf(" (no control file)"); 2122 printf("\n"); 2123 (void) fclose(f); 2124 } 2125 } 2126 2127 # endif /* QUEUE */ 2128 /* 2129 ** QUEUENAME -- build a file name in the queue directory for this envelope. 2130 ** 2131 ** Assigns an id code if one does not already exist. 2132 ** This code is very careful to avoid trashing existing files 2133 ** under any circumstances. 2134 ** 2135 ** Parameters: 2136 ** e -- envelope to build it in/from. 2137 ** type -- the file type, used as the first character 2138 ** of the file name. 2139 ** 2140 ** Returns: 2141 ** a pointer to the new file name (in a static buffer). 2142 ** 2143 ** Side Effects: 2144 ** If no id code is already assigned, queuename will 2145 ** assign an id code, create a qf file, and leave a 2146 ** locked, open-for-write file pointer in the envelope. 2147 */ 2148 2149 #ifndef ENOLCK 2150 # define ENOLCK -1 2151 #endif 2152 #ifndef ENOSPC 2153 # define ENOSPC -1 2154 #endif 2155 2156 char * 2157 queuename(e, type) 2158 register ENVELOPE *e; 2159 int type; 2160 { 2161 static pid_t pid = -1; 2162 static char c0; 2163 static char c1; 2164 static char c2; 2165 time_t now; 2166 struct tm *tm; 2167 static char buf[MAXNAME + 1]; 2168 2169 if (e->e_id == NULL) 2170 { 2171 char qf[MAXQFNAME]; 2172 2173 /* find a unique id */ 2174 if (pid != getpid()) 2175 { 2176 /* new process -- start back at "AA" */ 2177 pid = getpid(); 2178 now = curtime(); 2179 tm = localtime(&now); 2180 c0 = 'A' + tm->tm_hour; 2181 c1 = 'A'; 2182 c2 = 'A' - 1; 2183 } 2184 (void) snprintf(qf, sizeof qf, "qf%cAA%05d", c0, pid); 2185 2186 while (c1 < '~' || c2 < 'Z') 2187 { 2188 int i; 2189 int attempts = 0; 2190 2191 if (c2 >= 'Z') 2192 { 2193 c1++; 2194 c2 = 'A' - 1; 2195 } 2196 qf[3] = c1; 2197 qf[4] = ++c2; 2198 if (tTd(7, 20)) 2199 printf("queuename: trying \"%s\"\n", qf); 2200 2201 i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode); 2202 if (i < 0) 2203 { 2204 if (errno == EEXIST) 2205 continue; 2206 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 2207 qf, QueueDir, geteuid()); 2208 finis(FALSE, EX_UNAVAILABLE); 2209 } 2210 do 2211 { 2212 if (attempts > 0) 2213 sleep(attempts); 2214 e->e_lockfp = 0; 2215 if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB)) 2216 { 2217 e->e_lockfp = fdopen(i, "w"); 2218 break; 2219 } 2220 } while ((errno == ENOLCK || errno == ENOSPC) && 2221 attempts++ < 4); 2222 2223 /* Successful lock */ 2224 if (e->e_lockfp != 0) 2225 break; 2226 2227 #if !HASFLOCK 2228 if (errno != EAGAIN && errno != EACCES) 2229 #else 2230 if (errno != EWOULDBLOCK) 2231 #endif 2232 { 2233 syserr("queuename: Cannot lock \"%s\" in \"%s\" (euid=%d)", 2234 qf, QueueDir, geteuid()); 2235 finis(FALSE, EX_OSERR); 2236 } 2237 2238 /* a reader got the file; abandon it and try again */ 2239 (void) close(i); 2240 } 2241 if (c1 >= '~' && c2 >= 'Z') 2242 { 2243 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 2244 qf, QueueDir, geteuid()); 2245 finis(FALSE, EX_OSERR); 2246 } 2247 e->e_id = newstr(&qf[2]); 2248 define('i', e->e_id, e); 2249 if (tTd(7, 1)) 2250 printf("queuename: assigned id %s, env=%lx\n", 2251 e->e_id, (u_long) e); 2252 if (tTd(7, 9)) 2253 { 2254 printf(" lockfd="); 2255 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 2256 } 2257 if (LogLevel > 93) 2258 sm_syslog(LOG_DEBUG, e->e_id, "assigned id"); 2259 } 2260 2261 if (type == '\0') 2262 return (NULL); 2263 (void) snprintf(buf, sizeof buf, "%cf%s", type, e->e_id); 2264 if (tTd(7, 2)) 2265 printf("queuename: %s\n", buf); 2266 return (buf); 2267 } 2268 /* 2269 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 2270 ** 2271 ** Parameters: 2272 ** e -- the envelope to unlock. 2273 ** 2274 ** Returns: 2275 ** none 2276 ** 2277 ** Side Effects: 2278 ** unlocks the queue for `e'. 2279 */ 2280 2281 void 2282 unlockqueue(e) 2283 ENVELOPE *e; 2284 { 2285 if (tTd(51, 4)) 2286 printf("unlockqueue(%s)\n", 2287 e->e_id == NULL ? "NOQUEUE" : e->e_id); 2288 2289 /* if there is a lock file in the envelope, close it */ 2290 if (e->e_lockfp != NULL) 2291 xfclose(e->e_lockfp, "unlockqueue", e->e_id); 2292 e->e_lockfp = NULL; 2293 2294 /* don't create a queue id if we don't already have one */ 2295 if (e->e_id == NULL) 2296 return; 2297 2298 /* remove the transcript */ 2299 if (LogLevel > 87) 2300 sm_syslog(LOG_DEBUG, e->e_id, "unlock"); 2301 if (!tTd(51, 104)) 2302 xunlink(queuename(e, 'x')); 2303 2304 } 2305 /* 2306 ** SETCTLUSER -- create a controlling address 2307 ** 2308 ** Create a fake "address" given only a local login name; this is 2309 ** used as a "controlling user" for future recipient addresses. 2310 ** 2311 ** Parameters: 2312 ** user -- the user name of the controlling user. 2313 ** qfver -- the version stamp of this qf file. 2314 ** 2315 ** Returns: 2316 ** An address descriptor for the controlling user. 2317 ** 2318 ** Side Effects: 2319 ** none. 2320 */ 2321 2322 ADDRESS * 2323 setctluser(user, qfver) 2324 char *user; 2325 int qfver; 2326 { 2327 register ADDRESS *a; 2328 struct passwd *pw; 2329 char *p; 2330 2331 /* 2332 ** See if this clears our concept of controlling user. 2333 */ 2334 2335 if (user == NULL || *user == '\0') 2336 return NULL; 2337 2338 /* 2339 ** Set up addr fields for controlling user. 2340 */ 2341 2342 a = (ADDRESS *) xalloc(sizeof *a); 2343 bzero((char *) a, sizeof *a); 2344 2345 if (*user == '\0') 2346 { 2347 p = NULL; 2348 a->q_user = newstr(DefUser); 2349 } 2350 else if (*user == ':') 2351 { 2352 p = &user[1]; 2353 a->q_user = newstr(p); 2354 } 2355 else 2356 { 2357 p = strtok(user, ":"); 2358 a->q_user = newstr(user); 2359 if (qfver >= 2) 2360 { 2361 if ((p = strtok(NULL, ":")) != NULL) 2362 a->q_uid = atoi(p); 2363 if ((p = strtok(NULL, ":")) != NULL) 2364 a->q_gid = atoi(p); 2365 if ((p = strtok(NULL, ":")) != NULL) 2366 a->q_flags |= QGOODUID; 2367 } 2368 else if ((pw = sm_getpwnam(user)) != NULL) 2369 { 2370 if (strcmp(pw->pw_dir, "/") == 0) 2371 a->q_home = ""; 2372 else 2373 a->q_home = newstr(pw->pw_dir); 2374 a->q_uid = pw->pw_uid; 2375 a->q_gid = pw->pw_gid; 2376 a->q_flags |= QGOODUID; 2377 } 2378 } 2379 2380 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 2381 a->q_mailer = LocalMailer; 2382 if (p == NULL) 2383 a->q_paddr = a->q_user; 2384 else 2385 a->q_paddr = newstr(p); 2386 return a; 2387 } 2388 /* 2389 ** LOSEQFILE -- save the qf as Qf and try to let someone know 2390 ** 2391 ** Parameters: 2392 ** e -- the envelope (e->e_id will be used). 2393 ** why -- reported to whomever can hear. 2394 ** 2395 ** Returns: 2396 ** none. 2397 */ 2398 2399 void 2400 loseqfile(e, why) 2401 register ENVELOPE *e; 2402 char *why; 2403 { 2404 char *p; 2405 char buf[MAXQFNAME + 1]; 2406 2407 if (e == NULL || e->e_id == NULL) 2408 return; 2409 p = queuename(e, 'q'); 2410 if (strlen(p) > MAXQFNAME) 2411 { 2412 syserr("loseqfile: queuename (%s) too long", p); 2413 return; 2414 } 2415 strcpy(buf, p); 2416 p = queuename(e, 'Q'); 2417 if (rename(buf, p) < 0) 2418 syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid()); 2419 else if (LogLevel > 0) 2420 sm_syslog(LOG_ALERT, e->e_id, 2421 "Losing %s: %s", buf, why); 2422 } 2423