1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 # include "sendmail.h" 10 11 #ifndef lint 12 #ifdef QUEUE 13 static char sccsid[] = "@(#)queue.c 8.74 (Berkeley) 03/27/95 (with queueing)"; 14 #else 15 static char sccsid[] = "@(#)queue.c 8.74 (Berkeley) 03/27/95 (without queueing)"; 16 #endif 17 #endif /* not lint */ 18 19 # include <errno.h> 20 # include <pwd.h> 21 # include <dirent.h> 22 23 # ifdef QUEUE 24 25 /* 26 ** Work queue. 27 */ 28 29 struct work 30 { 31 char *w_name; /* name of control file */ 32 char *w_host; /* name of recipient host */ 33 bool w_lock; /* is message locked? */ 34 long w_pri; /* priority of message, see below */ 35 time_t w_ctime; /* creation time of message */ 36 struct work *w_next; /* next in queue */ 37 }; 38 39 typedef struct work WORK; 40 41 WORK *WorkQ; /* queue of things to be done */ 42 43 #define QF_VERSION 1 /* version number of this queue format */ 44 /* 45 ** QUEUEUP -- queue a message up for future transmission. 46 ** 47 ** Parameters: 48 ** e -- the envelope to queue up. 49 ** queueall -- if TRUE, queue all addresses, rather than 50 ** just those with the QQUEUEUP flag set. 51 ** announce -- if TRUE, tell when you are queueing up. 52 ** 53 ** Returns: 54 ** none. 55 ** 56 ** Side Effects: 57 ** The current request are saved in a control file. 58 ** The queue file is left locked. 59 */ 60 61 queueup(e, queueall, announce) 62 register ENVELOPE *e; 63 bool queueall; 64 bool announce; 65 { 66 char *qf; 67 register FILE *tfp; 68 register HDR *h; 69 register ADDRESS *q; 70 int fd; 71 int i; 72 bool newid; 73 register char *p; 74 MAILER nullmailer; 75 MCI mcibuf; 76 char buf[MAXLINE], tf[MAXLINE]; 77 78 /* 79 ** Create control file. 80 */ 81 82 newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags); 83 84 /* if newid, queuename will create a locked qf file in e->lockfp */ 85 strcpy(tf, queuename(e, 't')); 86 tfp = e->e_lockfp; 87 if (tfp == NULL) 88 newid = FALSE; 89 90 /* if newid, just write the qf file directly (instead of tf file) */ 91 if (!newid) 92 { 93 /* get a locked tf file */ 94 for (i = 0; i < 128; i++) 95 { 96 fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode); 97 if (fd < 0) 98 { 99 if (errno != EEXIST) 100 break; 101 #ifdef LOG 102 if (LogLevel > 0 && (i % 32) == 0) 103 syslog(LOG_ALERT, "queueup: cannot create %s, uid=%d: %s", 104 tf, geteuid(), errstring(errno)); 105 #endif 106 } 107 else 108 { 109 if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB)) 110 break; 111 #ifdef LOG 112 else if (LogLevel > 0 && (i % 32) == 0) 113 syslog(LOG_ALERT, "queueup: cannot lock %s: %s", 114 tf, errstring(errno)); 115 #endif 116 close(fd); 117 } 118 119 if ((i % 32) == 31) 120 { 121 /* save the old temp file away */ 122 (void) rename(tf, queuename(e, 'T')); 123 } 124 else 125 sleep(i % 32); 126 } 127 if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL) 128 { 129 printopenfds(TRUE); 130 syserr("!queueup: cannot create queue temp file %s, uid=%d", 131 tf, geteuid()); 132 } 133 } 134 135 if (tTd(40, 1)) 136 printf("\n>>>>> queueing %s%s queueall=%d >>>>>\n", e->e_id, 137 newid ? " (new id)" : "", queueall); 138 if (tTd(40, 3)) 139 { 140 extern void printenvflags(); 141 142 printf(" e_flags="); 143 printenvflags(e); 144 } 145 if (tTd(40, 32)) 146 { 147 printf(" sendq="); 148 printaddr(e->e_sendqueue, TRUE); 149 } 150 if (tTd(40, 9)) 151 { 152 printf(" tfp="); 153 dumpfd(fileno(tfp), TRUE, FALSE); 154 printf(" lockfp="); 155 if (e->e_lockfp == NULL) 156 printf("NULL\n"); 157 else 158 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 159 } 160 161 /* 162 ** If there is no data file yet, create one. 163 */ 164 165 if (!bitset(EF_HAS_DF, e->e_flags)) 166 { 167 register FILE *dfp; 168 char dfname[20]; 169 struct stat stbuf; 170 extern putbody(); 171 172 strcpy(dfname, queuename(e, 'd')); 173 fd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode); 174 if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL) 175 syserr("!queueup: cannot create data temp file %s, uid=%d", 176 dfname, geteuid()); 177 if (fstat(fd, &stbuf) < 0) 178 e->e_dfino = -1; 179 else 180 { 181 e->e_dfdev = stbuf.st_dev; 182 e->e_dfino = stbuf.st_ino; 183 } 184 e->e_flags |= EF_HAS_DF; 185 bzero(&mcibuf, sizeof mcibuf); 186 mcibuf.mci_out = dfp; 187 mcibuf.mci_mailer = FileMailer; 188 (*e->e_putbody)(&mcibuf, e, NULL); 189 (void) xfclose(dfp, "queueup dfp", e->e_id); 190 e->e_putbody = putbody; 191 } 192 193 /* 194 ** Output future work requests. 195 ** Priority and creation time should be first, since 196 ** they are required by orderq. 197 */ 198 199 /* output queue version number (must be first!) */ 200 fprintf(tfp, "V%d\n", QF_VERSION); 201 202 /* output message priority */ 203 fprintf(tfp, "P%ld\n", e->e_msgpriority); 204 205 /* output creation time */ 206 fprintf(tfp, "T%ld\n", e->e_ctime); 207 208 /* output last delivery time */ 209 fprintf(tfp, "K%ld\n", e->e_dtime); 210 211 /* output number of delivery attempts */ 212 fprintf(tfp, "N%d\n", e->e_ntries); 213 214 /* output inode number of data file */ 215 /* XXX should probably include device major/minor too */ 216 if (e->e_dfino != -1) 217 fprintf(tfp, "I%d/%d/%ld\n", 218 major(e->e_dfdev), minor(e->e_dfdev), e->e_dfino); 219 220 /* output body type */ 221 if (e->e_bodytype != NULL) 222 fprintf(tfp, "B%s\n", e->e_bodytype); 223 224 /* message from envelope, if it exists */ 225 if (e->e_message != NULL) 226 fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE)); 227 228 /* send various flag bits through */ 229 p = buf; 230 if (bitset(EF_WARNING, e->e_flags)) 231 *p++ = 'w'; 232 if (bitset(EF_RESPONSE, e->e_flags)) 233 *p++ = 'r'; 234 if (bitset(EF_HAS8BIT, e->e_flags)) 235 *p++ = '8'; 236 *p++ = '\0'; 237 if (buf[0] != '\0') 238 fprintf(tfp, "F%s\n", buf); 239 240 /* $r and $s and $_ macro values */ 241 if ((p = macvalue('r', e)) != NULL) 242 fprintf(tfp, "$r%s\n", denlstring(p, TRUE, FALSE)); 243 if ((p = macvalue('s', e)) != NULL) 244 fprintf(tfp, "$s%s\n", denlstring(p, TRUE, FALSE)); 245 if ((p = macvalue('_', e)) != NULL) 246 fprintf(tfp, "$_%s\n", denlstring(p, TRUE, FALSE)); 247 248 /* output name of sender */ 249 if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) 250 p = e->e_sender; 251 else 252 p = e->e_from.q_paddr; 253 fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE)); 254 255 /* output ESMTP-supplied "original" information */ 256 if (e->e_envid != NULL) 257 fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE)); 258 259 /* output list of recipient addresses */ 260 printctladdr(NULL, NULL); 261 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 262 { 263 if (bitset(QQUEUEUP, q->q_flags) || 264 (queueall && !bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))) 265 { 266 printctladdr(q, tfp); 267 if (q->q_orcpt != NULL) 268 fprintf(tfp, "Q%s\n", 269 denlstring(q->q_orcpt, TRUE, FALSE)); 270 putc('R', tfp); 271 if (bitset(QPRIMARY, q->q_flags)) 272 putc('P', tfp); 273 if (bitset(QPINGONSUCCESS, q->q_flags)) 274 putc('S', tfp); 275 if (bitset(QPINGONFAILURE, q->q_flags)) 276 putc('F', tfp); 277 if (bitset(QPINGONDELAY, q->q_flags)) 278 putc('D', tfp); 279 putc(':', tfp); 280 fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE)); 281 if (announce) 282 { 283 e->e_to = q->q_paddr; 284 message("queued"); 285 if (LogLevel > 8) 286 logdelivery(NULL, NULL, "queued", 287 NULL, (time_t) 0, e); 288 e->e_to = NULL; 289 } 290 if (tTd(40, 1)) 291 { 292 printf("queueing "); 293 printaddr(q, FALSE); 294 } 295 } 296 } 297 298 /* 299 ** Output headers for this message. 300 ** Expand macros completely here. Queue run will deal with 301 ** everything as absolute headers. 302 ** All headers that must be relative to the recipient 303 ** can be cracked later. 304 ** We set up a "null mailer" -- i.e., a mailer that will have 305 ** no effect on the addresses as they are output. 306 */ 307 308 bzero((char *) &nullmailer, sizeof nullmailer); 309 nullmailer.m_re_rwset = nullmailer.m_rh_rwset = 310 nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1; 311 nullmailer.m_eol = "\n"; 312 bzero(&mcibuf, sizeof mcibuf); 313 mcibuf.mci_mailer = &nullmailer; 314 mcibuf.mci_out = tfp; 315 316 define('g', "\201f", e); 317 for (h = e->e_header; h != NULL; h = h->h_link) 318 { 319 extern bool bitzerop(); 320 321 /* don't output null headers */ 322 if (h->h_value == NULL || h->h_value[0] == '\0') 323 continue; 324 325 /* don't output resent headers on non-resent messages */ 326 if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) 327 continue; 328 329 /* expand macros; if null, don't output header at all */ 330 if (bitset(H_DEFAULT, h->h_flags)) 331 { 332 (void) expand(h->h_value, buf, sizeof buf, e); 333 if (buf[0] == '\0') 334 continue; 335 } 336 337 /* output this header */ 338 fprintf(tfp, "H"); 339 340 /* if conditional, output the set of conditions */ 341 if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags)) 342 { 343 int j; 344 345 (void) putc('?', tfp); 346 for (j = '\0'; j <= '\177'; j++) 347 if (bitnset(j, h->h_mflags)) 348 (void) putc(j, tfp); 349 (void) putc('?', tfp); 350 } 351 352 /* output the header: expand macros, convert addresses */ 353 if (bitset(H_DEFAULT, h->h_flags)) 354 { 355 fprintf(tfp, "%s: %s\n", h->h_field, buf); 356 } 357 else if (bitset(H_FROM|H_RCPT, h->h_flags)) 358 { 359 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 360 FILE *savetrace = TrafficLogFile; 361 362 TrafficLogFile = NULL; 363 364 if (bitset(H_FROM, h->h_flags)) 365 oldstyle = FALSE; 366 367 commaize(h, h->h_value, oldstyle, &mcibuf, e); 368 369 TrafficLogFile = savetrace; 370 } 371 else 372 fprintf(tfp, "%s: %s\n", h->h_field, h->h_value); 373 } 374 375 /* 376 ** Clean up. 377 */ 378 379 if (fflush(tfp) < 0 || fsync(fileno(tfp)) < 0 || ferror(tfp)) 380 { 381 if (newid) 382 syserr("!552 Error writing control file %s", tf); 383 else 384 syserr("!452 Error writing control file %s", tf); 385 } 386 387 if (!newid) 388 { 389 /* rename (locked) tf to be (locked) qf */ 390 qf = queuename(e, 'q'); 391 if (rename(tf, qf) < 0) 392 syserr("cannot rename(%s, %s), uid=%d", 393 tf, qf, geteuid()); 394 395 /* close and unlock old (locked) qf */ 396 if (e->e_lockfp != NULL) 397 (void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id); 398 e->e_lockfp = tfp; 399 } 400 else 401 qf = tf; 402 errno = 0; 403 e->e_flags |= EF_INQUEUE; 404 405 # ifdef LOG 406 /* save log info */ 407 if (LogLevel > 79) 408 syslog(LOG_DEBUG, "%s: queueup, qf=%s", e->e_id, qf); 409 # endif /* LOG */ 410 411 if (tTd(40, 1)) 412 printf("<<<<< done queueing %s <<<<<\n\n", e->e_id); 413 return; 414 } 415 416 printctladdr(a, tfp) 417 register ADDRESS *a; 418 FILE *tfp; 419 { 420 char *uname; 421 register struct passwd *pw; 422 register ADDRESS *q; 423 uid_t uid; 424 static ADDRESS *lastctladdr; 425 static uid_t lastuid; 426 427 /* initialization */ 428 if (a == NULL || a->q_alias == NULL || tfp == NULL) 429 { 430 if (lastctladdr != NULL && tfp != NULL) 431 fprintf(tfp, "C\n"); 432 lastctladdr = NULL; 433 lastuid = 0; 434 return; 435 } 436 437 /* find the active uid */ 438 q = getctladdr(a); 439 if (q == NULL) 440 uid = 0; 441 else 442 uid = q->q_uid; 443 a = a->q_alias; 444 445 /* check to see if this is the same as last time */ 446 if (lastctladdr != NULL && uid == lastuid && 447 strcmp(lastctladdr->q_paddr, a->q_paddr) == 0) 448 return; 449 lastuid = uid; 450 lastctladdr = a; 451 452 if (uid == 0 || (pw = getpwuid(uid)) == NULL) 453 uname = ""; 454 else 455 uname = pw->pw_name; 456 457 fprintf(tfp, "C%s:%s\n", uname, denlstring(a->q_paddr, TRUE, FALSE)); 458 } 459 /* 460 ** RUNQUEUE -- run the jobs in the queue. 461 ** 462 ** Gets the stuff out of the queue in some presumably logical 463 ** order and processes them. 464 ** 465 ** Parameters: 466 ** forkflag -- TRUE if the queue scanning should be done in 467 ** a child process. We double-fork so it is not our 468 ** child and we don't have to clean up after it. 469 ** 470 ** Returns: 471 ** none. 472 ** 473 ** Side Effects: 474 ** runs things in the mail queue. 475 */ 476 477 ENVELOPE QueueEnvelope; /* the queue run envelope */ 478 479 void 480 runqueue(forkflag) 481 bool forkflag; 482 { 483 register ENVELOPE *e; 484 int njobs; 485 int sequenceno = 0; 486 extern ENVELOPE BlankEnvelope; 487 488 /* 489 ** If no work will ever be selected, don't even bother reading 490 ** the queue. 491 */ 492 493 CurrentLA = getla(); /* get load average */ 494 495 if (shouldqueue(0L, curtime())) 496 { 497 if (Verbose) 498 printf("Skipping queue run -- load average too high\n"); 499 if (forkflag && QueueIntvl != 0) 500 (void) setevent(QueueIntvl, runqueue, TRUE); 501 return; 502 } 503 504 /* 505 ** See if we want to go off and do other useful work. 506 */ 507 508 if (forkflag) 509 { 510 int pid; 511 #ifdef SIGCHLD 512 extern void reapchild(); 513 514 (void) setsignal(SIGCHLD, reapchild); 515 #endif 516 517 pid = dofork(); 518 if (pid != 0) 519 { 520 /* parent -- pick up intermediate zombie */ 521 #ifndef SIGCHLD 522 (void) waitfor(pid); 523 #endif /* SIGCHLD */ 524 if (QueueIntvl != 0) 525 (void) setevent(QueueIntvl, runqueue, TRUE); 526 return; 527 } 528 /* child -- double fork */ 529 #ifndef SIGCHLD 530 if (fork() != 0) 531 exit(EX_OK); 532 #else /* SIGCHLD */ 533 (void) setsignal(SIGCHLD, SIG_DFL); 534 #endif /* SIGCHLD */ 535 } 536 537 setproctitle("running queue: %s", QueueDir); 538 539 # ifdef LOG 540 if (LogLevel > 69) 541 syslog(LOG_DEBUG, "runqueue %s, pid=%d, forkflag=%d", 542 QueueDir, getpid(), forkflag); 543 # endif /* LOG */ 544 545 /* 546 ** Release any resources used by the daemon code. 547 */ 548 549 # ifdef DAEMON 550 clrdaemon(); 551 # endif /* DAEMON */ 552 553 /* force it to run expensive jobs */ 554 NoConnect = FALSE; 555 556 /* 557 ** Create ourselves an envelope 558 */ 559 560 CurEnv = &QueueEnvelope; 561 e = newenvelope(&QueueEnvelope, CurEnv); 562 e->e_flags = BlankEnvelope.e_flags; 563 564 /* 565 ** Make sure the alias database is open. 566 */ 567 568 initmaps(FALSE, e); 569 570 /* 571 ** Start making passes through the queue. 572 ** First, read and sort the entire queue. 573 ** Then, process the work in that order. 574 ** But if you take too long, start over. 575 */ 576 577 /* order the existing work requests */ 578 njobs = orderq(FALSE); 579 580 /* process them once at a time */ 581 while (WorkQ != NULL) 582 { 583 WORK *w = WorkQ; 584 585 WorkQ = WorkQ->w_next; 586 587 /* 588 ** Ignore jobs that are too expensive for the moment. 589 */ 590 591 sequenceno++; 592 if (shouldqueue(w->w_pri, w->w_ctime)) 593 { 594 if (Verbose) 595 printf("\nSkipping %s (sequence %d of %d)\n", 596 w->w_name + 2, sequenceno, njobs); 597 } 598 else 599 { 600 pid_t pid; 601 extern pid_t dowork(); 602 603 if (Verbose) 604 printf("\nRunning %s (sequence %d of %d)\n", 605 w->w_name + 2, sequenceno, njobs); 606 pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e); 607 errno = 0; 608 if (pid != 0) 609 (void) waitfor(pid); 610 } 611 free(w->w_name); 612 if (w->w_host) 613 free(w->w_host); 614 free((char *) w); 615 } 616 617 /* exit without the usual cleanup */ 618 e->e_id = NULL; 619 finis(); 620 } 621 /* 622 ** ORDERQ -- order the work queue. 623 ** 624 ** Parameters: 625 ** doall -- if set, include everything in the queue (even 626 ** the jobs that cannot be run because the load 627 ** average is too high). Otherwise, exclude those 628 ** jobs. 629 ** 630 ** Returns: 631 ** The number of request in the queue (not necessarily 632 ** the number of requests in WorkQ however). 633 ** 634 ** Side Effects: 635 ** Sets WorkQ to the queue of available work, in order. 636 */ 637 638 # define NEED_P 001 639 # define NEED_T 002 640 # define NEED_R 004 641 # define NEED_S 010 642 643 orderq(doall) 644 bool doall; 645 { 646 register struct dirent *d; 647 register WORK *w; 648 DIR *f; 649 register int i; 650 WORK wlist[QUEUESIZE+1]; 651 int wn = -1; 652 int wc; 653 654 if (tTd(41, 1)) 655 { 656 printf("orderq:\n"); 657 if (QueueLimitId != NULL) 658 printf("\tQueueLimitId = %s\n", QueueLimitId); 659 if (QueueLimitSender != NULL) 660 printf("\tQueueLimitSender = %s\n", QueueLimitSender); 661 if (QueueLimitRecipient != NULL) 662 printf("\tQueueLimitRecipient = %s\n", QueueLimitRecipient); 663 } 664 665 /* clear out old WorkQ */ 666 for (w = WorkQ; w != NULL; ) 667 { 668 register WORK *nw = w->w_next; 669 670 WorkQ = nw; 671 free(w->w_name); 672 if (w->w_host) 673 free(w->w_host); 674 free((char *) w); 675 w = nw; 676 } 677 678 /* open the queue directory */ 679 f = opendir("."); 680 if (f == NULL) 681 { 682 syserr("orderq: cannot open \"%s\" as \".\"", QueueDir); 683 return (0); 684 } 685 686 /* 687 ** Read the work directory. 688 */ 689 690 while ((d = readdir(f)) != NULL) 691 { 692 FILE *cf; 693 register char *p; 694 char lbuf[MAXNAME + 1]; 695 extern bool strcontainedin(); 696 697 /* is this an interesting entry? */ 698 if (d->d_name[0] != 'q' || d->d_name[1] != 'f') 699 continue; 700 701 if (QueueLimitId != NULL && 702 !strcontainedin(QueueLimitId, d->d_name)) 703 continue; 704 705 #ifdef PICKY_QF_NAME_CHECK 706 /* 707 ** Check queue name for plausibility. This handles 708 ** both old and new type ids. 709 */ 710 711 p = d->d_name + 2; 712 if (isupper(p[0]) && isupper(p[2])) 713 p += 3; 714 else if (isupper(p[1])) 715 p += 2; 716 else 717 p = d->d_name; 718 for (i = 0; isdigit(*p); p++) 719 i++; 720 if (i < 5 || *p != '\0') 721 { 722 if (Verbose) 723 printf("orderq: bogus qf name %s\n", d->d_name); 724 # ifdef LOG 725 if (LogLevel > 0) 726 syslog(LOG_ALERT, "orderq: bogus qf name %s", 727 d->d_name); 728 # endif 729 if (strlen(d->d_name) > MAXNAME) 730 d->d_name[MAXNAME] = '\0'; 731 strcpy(lbuf, d->d_name); 732 lbuf[0] = 'Q'; 733 (void) rename(d->d_name, lbuf); 734 continue; 735 } 736 #endif 737 738 /* open control file (if not too many files) */ 739 if (++wn >= QUEUESIZE) 740 continue; 741 742 cf = fopen(d->d_name, "r"); 743 if (cf == NULL) 744 { 745 /* this may be some random person sending hir msgs */ 746 /* syserr("orderq: cannot open %s", cbuf); */ 747 if (tTd(41, 2)) 748 printf("orderq: cannot open %s (%d)\n", 749 d->d_name, errno); 750 errno = 0; 751 wn--; 752 continue; 753 } 754 w = &wlist[wn]; 755 w->w_name = newstr(d->d_name); 756 w->w_host = NULL; 757 w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB); 758 759 /* make sure jobs in creation don't clog queue */ 760 w->w_pri = 0x7fffffff; 761 w->w_ctime = 0; 762 763 /* extract useful information */ 764 i = NEED_P | NEED_T; 765 if (QueueLimitSender != NULL) 766 i |= NEED_S; 767 if (QueueSortOrder == QS_BYHOST || QueueLimitRecipient != NULL) 768 i |= NEED_R; 769 while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) 770 { 771 extern long atol(); 772 extern bool strcontainedin(); 773 774 switch (lbuf[0]) 775 { 776 case 'P': 777 w->w_pri = atol(&lbuf[1]); 778 i &= ~NEED_P; 779 break; 780 781 case 'T': 782 w->w_ctime = atol(&lbuf[1]); 783 i &= ~NEED_T; 784 break; 785 786 case 'R': 787 if (w->w_host == NULL && 788 (p = strrchr(&lbuf[1], '@')) != NULL) 789 w->w_host = newstr(&p[1]); 790 if (QueueLimitRecipient == NULL || 791 strcontainedin(QueueLimitRecipient, &lbuf[1])) 792 i &= ~NEED_R; 793 break; 794 795 case 'S': 796 if (QueueLimitSender != NULL && 797 strcontainedin(QueueLimitSender, &lbuf[1])) 798 i &= ~NEED_S; 799 break; 800 } 801 } 802 (void) fclose(cf); 803 804 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 805 bitset(NEED_R|NEED_S, i)) 806 { 807 /* don't even bother sorting this job in */ 808 free(w->w_name); 809 if (w->w_host) 810 free(w->w_host); 811 wn--; 812 } 813 } 814 (void) closedir(f); 815 wn++; 816 817 wc = min(wn, QUEUESIZE); 818 819 if (QueueSortOrder == QS_BYHOST) 820 { 821 extern workcmpf1(); 822 extern workcmpf2(); 823 824 /* 825 ** Sort the work directory for the first time, 826 ** based on host name, lock status, and priority. 827 */ 828 829 qsort((char *) wlist, wc, sizeof *wlist, workcmpf1); 830 831 /* 832 ** If one message to host is locked, "lock" all messages 833 ** to that host. 834 */ 835 836 i = 0; 837 while (i < wc) 838 { 839 if (!wlist[i].w_lock) 840 { 841 i++; 842 continue; 843 } 844 w = &wlist[i]; 845 while (++i < wc) 846 { 847 if (wlist[i].w_host == NULL && 848 w->w_host == NULL) 849 wlist[i].w_lock = TRUE; 850 else if (wlist[i].w_host != NULL && 851 w->w_host != NULL && 852 strcmp(wlist[i].w_host, w->w_host) == 0) 853 wlist[i].w_lock = TRUE; 854 else 855 break; 856 } 857 } 858 859 /* 860 ** Sort the work directory for the second time, 861 ** based on lock status, host name, and priority. 862 */ 863 864 qsort((char *) wlist, wc, sizeof *wlist, workcmpf2); 865 } 866 else 867 { 868 extern workcmpf0(); 869 870 /* 871 ** Simple sort based on queue priority only. 872 */ 873 874 qsort((char *) wlist, wc, sizeof *wlist, workcmpf0); 875 } 876 877 /* 878 ** Convert the work list into canonical form. 879 ** Should be turning it into a list of envelopes here perhaps. 880 */ 881 882 WorkQ = NULL; 883 for (i = wc; --i >= 0; ) 884 { 885 w = (WORK *) xalloc(sizeof *w); 886 w->w_name = wlist[i].w_name; 887 w->w_host = wlist[i].w_host; 888 w->w_lock = wlist[i].w_lock; 889 w->w_pri = wlist[i].w_pri; 890 w->w_ctime = wlist[i].w_ctime; 891 w->w_next = WorkQ; 892 WorkQ = w; 893 } 894 895 if (tTd(40, 1)) 896 { 897 for (w = WorkQ; w != NULL; w = w->w_next) 898 printf("%32s: pri=%ld\n", w->w_name, w->w_pri); 899 } 900 901 return (wn); 902 } 903 /* 904 ** WORKCMPF0 -- simple priority-only compare function. 905 ** 906 ** Parameters: 907 ** a -- the first argument. 908 ** b -- the second argument. 909 ** 910 ** Returns: 911 ** -1 if a < b 912 ** 0 if a == b 913 ** +1 if a > b 914 ** 915 ** Side Effects: 916 ** none. 917 */ 918 919 workcmpf0(a, b) 920 register WORK *a; 921 register WORK *b; 922 { 923 long pa = a->w_pri; 924 long pb = b->w_pri; 925 926 if (pa == pb) 927 return 0; 928 else if (pa > pb) 929 return 1; 930 else 931 return -1; 932 } 933 /* 934 ** WORKCMPF1 -- first compare function for ordering work based on host name. 935 ** 936 ** Sorts on host name, lock status, and priority in that order. 937 ** 938 ** Parameters: 939 ** a -- the first argument. 940 ** b -- the second argument. 941 ** 942 ** Returns: 943 ** <0 if a < b 944 ** 0 if a == b 945 ** >0 if a > b 946 ** 947 ** Side Effects: 948 ** none. 949 */ 950 951 workcmpf1(a, b) 952 register WORK *a; 953 register WORK *b; 954 { 955 int i; 956 957 /* host name */ 958 if (a->w_host != NULL && b->w_host == NULL) 959 return 1; 960 else if (a->w_host == NULL && b->w_host != NULL) 961 return -1; 962 if (a->w_host != NULL && b->w_host != NULL && 963 (i = strcmp(a->w_host, b->w_host))) 964 return i; 965 966 /* lock status */ 967 if (a->w_lock != b->w_lock) 968 return b->w_lock - a->w_lock; 969 970 /* job priority */ 971 return a->w_pri - b->w_pri; 972 } 973 /* 974 ** WORKCMPF2 -- second compare function for ordering work based on host name. 975 ** 976 ** Sorts on lock status, host name, and priority in that order. 977 ** 978 ** Parameters: 979 ** a -- the first argument. 980 ** b -- the second argument. 981 ** 982 ** Returns: 983 ** <0 if a < b 984 ** 0 if a == b 985 ** >0 if a > b 986 ** 987 ** Side Effects: 988 ** none. 989 */ 990 991 workcmpf2(a, b) 992 register WORK *a; 993 register WORK *b; 994 { 995 int i; 996 997 /* lock status */ 998 if (a->w_lock != b->w_lock) 999 return a->w_lock - b->w_lock; 1000 1001 /* host name */ 1002 if (a->w_host != NULL && b->w_host == NULL) 1003 return 1; 1004 else if (a->w_host == NULL && b->w_host != NULL) 1005 return -1; 1006 if (a->w_host != NULL && b->w_host != NULL && 1007 (i = strcmp(a->w_host, b->w_host))) 1008 return i; 1009 1010 /* job priority */ 1011 return a->w_pri - b->w_pri; 1012 } 1013 /* 1014 ** DOWORK -- do a work request. 1015 ** 1016 ** Parameters: 1017 ** id -- the ID of the job to run. 1018 ** forkflag -- if set, run this in background. 1019 ** requeueflag -- if set, reinstantiate the queue quickly. 1020 ** This is used when expanding aliases in the queue. 1021 ** If forkflag is also set, it doesn't wait for the 1022 ** child. 1023 ** e - the envelope in which to run it. 1024 ** 1025 ** Returns: 1026 ** process id of process that is running the queue job. 1027 ** 1028 ** Side Effects: 1029 ** The work request is satisfied if possible. 1030 */ 1031 1032 pid_t 1033 dowork(id, forkflag, requeueflag, e) 1034 char *id; 1035 bool forkflag; 1036 bool requeueflag; 1037 register ENVELOPE *e; 1038 { 1039 register pid_t pid; 1040 extern bool readqf(); 1041 1042 if (tTd(40, 1)) 1043 printf("dowork(%s)\n", id); 1044 1045 /* 1046 ** Fork for work. 1047 */ 1048 1049 if (forkflag) 1050 { 1051 pid = fork(); 1052 if (pid < 0) 1053 { 1054 syserr("dowork: cannot fork"); 1055 return 0; 1056 } 1057 else if (pid > 0) 1058 { 1059 /* parent -- clean out connection cache */ 1060 mci_flush(FALSE, NULL); 1061 } 1062 } 1063 else 1064 { 1065 pid = 0; 1066 } 1067 1068 if (pid == 0) 1069 { 1070 /* 1071 ** CHILD 1072 ** Lock the control file to avoid duplicate deliveries. 1073 ** Then run the file as though we had just read it. 1074 ** We save an idea of the temporary name so we 1075 ** can recover on interrupt. 1076 */ 1077 1078 /* set basic modes, etc. */ 1079 (void) alarm(0); 1080 clearenvelope(e, FALSE); 1081 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 1082 e->e_errormode = EM_MAIL; 1083 e->e_id = id; 1084 GrabTo = UseErrorsTo = FALSE; 1085 ExitStat = EX_OK; 1086 if (forkflag) 1087 { 1088 disconnect(1, e); 1089 OpMode = MD_DELIVER; 1090 } 1091 # ifdef LOG 1092 if (LogLevel > 76) 1093 syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id, 1094 getpid()); 1095 # endif /* LOG */ 1096 1097 /* don't use the headers from sendmail.cf... */ 1098 e->e_header = NULL; 1099 1100 /* read the queue control file -- return if locked */ 1101 if (!readqf(e)) 1102 { 1103 if (tTd(40, 4)) 1104 printf("readqf(%s) failed\n", e->e_id); 1105 if (forkflag) 1106 exit(EX_OK); 1107 else 1108 return 0; 1109 } 1110 1111 e->e_flags |= EF_INQUEUE; 1112 1113 /* if this has been tried recently, let it be */ 1114 if (e->e_ntries > 0 && (curtime() - e->e_dtime) < MinQueueAge) 1115 { 1116 char *howlong = pintvl(curtime() - e->e_dtime, TRUE); 1117 1118 e->e_flags |= EF_KEEPQUEUE; 1119 if (Verbose || tTd(40, 8)) 1120 printf("%s: too young (%s)\n", 1121 e->e_id, howlong); 1122 #ifdef LOG 1123 if (LogLevel > 19) 1124 syslog(LOG_DEBUG, "%s: too young (%s)", 1125 e->e_id, howlong); 1126 #endif 1127 } 1128 else 1129 { 1130 eatheader(e, requeueflag); 1131 1132 if (requeueflag) 1133 queueup(e, TRUE, FALSE); 1134 1135 /* do the delivery */ 1136 sendall(e, SM_DELIVER); 1137 } 1138 1139 /* finish up and exit */ 1140 if (forkflag) 1141 finis(); 1142 else 1143 dropenvelope(e); 1144 } 1145 e->e_id = NULL; 1146 return pid; 1147 } 1148 /* 1149 ** READQF -- read queue file and set up environment. 1150 ** 1151 ** Parameters: 1152 ** e -- the envelope of the job to run. 1153 ** 1154 ** Returns: 1155 ** TRUE if it successfully read the queue file. 1156 ** FALSE otherwise. 1157 ** 1158 ** Side Effects: 1159 ** The queue file is returned locked. 1160 */ 1161 1162 bool 1163 readqf(e) 1164 register ENVELOPE *e; 1165 { 1166 register FILE *qfp; 1167 ADDRESS *ctladdr; 1168 struct stat st; 1169 char *bp; 1170 int qfver = 0; 1171 register char *p; 1172 char *orcpt = NULL; 1173 char qf[20]; 1174 char buf[MAXLINE]; 1175 extern long atol(); 1176 extern ADDRESS *setctluser(); 1177 extern void loseqfile(); 1178 1179 /* 1180 ** Read and process the file. 1181 */ 1182 1183 strcpy(qf, queuename(e, 'q')); 1184 qfp = fopen(qf, "r+"); 1185 if (qfp == NULL) 1186 { 1187 if (tTd(40, 8)) 1188 printf("readqf(%s): fopen failure (%s)\n", 1189 qf, errstring(errno)); 1190 if (errno != ENOENT) 1191 syserr("readqf: no control file %s", qf); 1192 return FALSE; 1193 } 1194 1195 if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB)) 1196 { 1197 /* being processed by another queuer */ 1198 if (Verbose || tTd(40, 8)) 1199 printf("%s: locked\n", e->e_id); 1200 # ifdef LOG 1201 if (LogLevel > 19) 1202 syslog(LOG_DEBUG, "%s: locked", e->e_id); 1203 # endif /* LOG */ 1204 (void) fclose(qfp); 1205 return FALSE; 1206 } 1207 1208 /* 1209 ** Check the queue file for plausibility to avoid attacks. 1210 */ 1211 1212 if (fstat(fileno(qfp), &st) < 0) 1213 { 1214 /* must have been being processed by someone else */ 1215 if (tTd(40, 8)) 1216 printf("readqf(%s): fstat failure (%s)\n", 1217 qf, errstring(errno)); 1218 fclose(qfp); 1219 return FALSE; 1220 } 1221 1222 if (st.st_uid != geteuid() || bitset(S_IWOTH|S_IWGRP, st.st_mode)) 1223 { 1224 # ifdef LOG 1225 if (LogLevel > 0) 1226 { 1227 syslog(LOG_ALERT, "%s: bogus queue file, uid=%d, mode=%o", 1228 e->e_id, st.st_uid, st.st_mode); 1229 } 1230 # endif /* LOG */ 1231 if (tTd(40, 8)) 1232 printf("readqf(%s): bogus file\n", qf); 1233 loseqfile(e, "bogus file uid in mqueue"); 1234 fclose(qfp); 1235 return FALSE; 1236 } 1237 1238 if (st.st_size == 0) 1239 { 1240 /* must be a bogus file -- just remove it */ 1241 (void) unlink(qf); 1242 fclose(qfp); 1243 return FALSE; 1244 } 1245 1246 if (st.st_nlink == 0) 1247 { 1248 /* 1249 ** Race condition -- we got a file just as it was being 1250 ** unlinked. Just assume it is zero length. 1251 */ 1252 1253 fclose(qfp); 1254 return FALSE; 1255 } 1256 1257 /* good file -- save this lock */ 1258 e->e_lockfp = qfp; 1259 1260 /* do basic system initialization */ 1261 initsys(e); 1262 define('i', e->e_id, e); 1263 1264 LineNumber = 0; 1265 e->e_flags |= EF_GLOBALERRS; 1266 OpMode = MD_DELIVER; 1267 ctladdr = NULL; 1268 e->e_dfino = -1; 1269 e->e_msgsize = -1; 1270 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 1271 { 1272 register char *p; 1273 u_long qflags; 1274 ADDRESS *q; 1275 1276 if (tTd(40, 4)) 1277 printf("+++++ %s\n", bp); 1278 switch (bp[0]) 1279 { 1280 case 'V': /* queue file version number */ 1281 qfver = atoi(&bp[1]); 1282 if (qfver > QF_VERSION) 1283 { 1284 syserr("Version number in qf (%d) greater than max (%d)", 1285 qfver, QF_VERSION); 1286 } 1287 break; 1288 1289 case 'C': /* specify controlling user */ 1290 ctladdr = setctluser(&bp[1]); 1291 break; 1292 1293 case 'Q': /* original recipient */ 1294 orcpt = newstr(&bp[1]); 1295 break; 1296 1297 case 'R': /* specify recipient */ 1298 p = bp; 1299 qflags = 0; 1300 if (qfver >= 1) 1301 { 1302 /* get flag bits */ 1303 while (*++p != '\0' && *p != ':') 1304 { 1305 switch (*p) 1306 { 1307 case 'S': 1308 qflags |= QPINGONSUCCESS; 1309 break; 1310 1311 case 'F': 1312 qflags |= QPINGONFAILURE; 1313 break; 1314 1315 case 'D': 1316 qflags |= QPINGONDELAY; 1317 break; 1318 1319 case 'P': 1320 qflags |= QPRIMARY; 1321 break; 1322 } 1323 } 1324 } 1325 else 1326 qflags |= QPRIMARY; 1327 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e); 1328 if (q != NULL) 1329 { 1330 q->q_alias = ctladdr; 1331 q->q_flags |= qflags; 1332 q->q_orcpt = orcpt; 1333 (void) recipient(q, &e->e_sendqueue, 0, e); 1334 } 1335 orcpt = NULL; 1336 break; 1337 1338 case 'E': /* specify error recipient */ 1339 /* no longer used */ 1340 break; 1341 1342 case 'H': /* header */ 1343 (void) chompheader(&bp[1], FALSE, e); 1344 break; 1345 1346 case 'M': /* message */ 1347 /* ignore this; we want a new message next time */ 1348 break; 1349 1350 case 'S': /* sender */ 1351 setsender(newstr(&bp[1]), e, NULL, TRUE); 1352 break; 1353 1354 case 'B': /* body type */ 1355 e->e_bodytype = newstr(&bp[1]); 1356 break; 1357 1358 case 'D': /* data file name */ 1359 /* obsolete -- ignore */ 1360 break; 1361 1362 case 'T': /* init time */ 1363 e->e_ctime = atol(&bp[1]); 1364 break; 1365 1366 case 'I': /* data file's inode number */ 1367 if (e->e_dfino == -1) 1368 e->e_dfino = atol(&buf[1]); 1369 break; 1370 1371 case 'K': /* time of last deliver attempt */ 1372 e->e_dtime = atol(&buf[1]); 1373 break; 1374 1375 case 'N': /* number of delivery attempts */ 1376 e->e_ntries = atoi(&buf[1]); 1377 break; 1378 1379 case 'P': /* message priority */ 1380 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 1381 break; 1382 1383 case 'F': /* flag bits */ 1384 for (p = &bp[1]; *p != '\0'; p++) 1385 { 1386 switch (*p) 1387 { 1388 case 'w': /* warning sent */ 1389 e->e_flags |= EF_WARNING; 1390 break; 1391 1392 case 'r': /* response */ 1393 e->e_flags |= EF_RESPONSE; 1394 break; 1395 1396 case '8': /* has 8 bit data */ 1397 e->e_flags |= EF_HAS8BIT; 1398 break; 1399 } 1400 } 1401 break; 1402 1403 case 'Z': /* original envelope id from ESMTP */ 1404 e->e_envid = newstr(&bp[1]); 1405 break; 1406 1407 case '$': /* define macro */ 1408 define(bp[1], newstr(&bp[2]), e); 1409 break; 1410 1411 case '\0': /* blank line; ignore */ 1412 break; 1413 1414 default: 1415 syserr("readqf: %s: line %d: bad line \"%s\"", 1416 qf, LineNumber, bp); 1417 fclose(qfp); 1418 loseqfile(e, "unrecognized line"); 1419 return FALSE; 1420 } 1421 1422 if (bp != buf) 1423 free(bp); 1424 } 1425 1426 /* 1427 ** If we haven't read any lines, this queue file is empty. 1428 ** Arrange to remove it without referencing any null pointers. 1429 */ 1430 1431 if (LineNumber == 0) 1432 { 1433 errno = 0; 1434 e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; 1435 } 1436 else 1437 { 1438 /* 1439 ** Arrange to read the data file. 1440 */ 1441 1442 p = queuename(e, 'd'); 1443 e->e_dfp = fopen(p, "r"); 1444 if (e->e_dfp == NULL) 1445 { 1446 syserr("readqf: cannot open %s", p); 1447 } 1448 else 1449 { 1450 e->e_flags |= EF_HAS_DF; 1451 if (fstat(fileno(e->e_dfp), &st) >= 0) 1452 { 1453 e->e_msgsize = st.st_size; 1454 e->e_dfdev = st.st_dev; 1455 e->e_dfino = st.st_ino; 1456 } 1457 } 1458 } 1459 1460 return TRUE; 1461 } 1462 /* 1463 ** PRINTQUEUE -- print out a representation of the mail queue 1464 ** 1465 ** Parameters: 1466 ** none. 1467 ** 1468 ** Returns: 1469 ** none. 1470 ** 1471 ** Side Effects: 1472 ** Prints a listing of the mail queue on the standard output. 1473 */ 1474 1475 printqueue() 1476 { 1477 register WORK *w; 1478 FILE *f; 1479 int nrequests; 1480 char buf[MAXLINE]; 1481 1482 /* 1483 ** Check for permission to print the queue 1484 */ 1485 1486 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 1487 { 1488 struct stat st; 1489 # ifdef NGROUPS 1490 int n; 1491 GIDSET_T gidset[NGROUPS]; 1492 # endif 1493 1494 if (stat(QueueDir, &st) < 0) 1495 { 1496 syserr("Cannot stat %s", QueueDir); 1497 return; 1498 } 1499 # ifdef NGROUPS 1500 n = getgroups(NGROUPS, gidset); 1501 while (--n >= 0) 1502 { 1503 if (gidset[n] == st.st_gid) 1504 break; 1505 } 1506 if (n < 0) 1507 # else 1508 if (RealGid != st.st_gid) 1509 # endif 1510 { 1511 usrerr("510 You are not permitted to see the queue"); 1512 setstat(EX_NOPERM); 1513 return; 1514 } 1515 } 1516 1517 /* 1518 ** Read and order the queue. 1519 */ 1520 1521 nrequests = orderq(TRUE); 1522 1523 /* 1524 ** Print the work list that we have read. 1525 */ 1526 1527 /* first see if there is anything */ 1528 if (nrequests <= 0) 1529 { 1530 printf("Mail queue is empty\n"); 1531 return; 1532 } 1533 1534 CurrentLA = getla(); /* get load average */ 1535 1536 printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s"); 1537 if (nrequests > QUEUESIZE) 1538 printf(", only %d printed", QUEUESIZE); 1539 if (Verbose) 1540 printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n"); 1541 else 1542 printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); 1543 for (w = WorkQ; w != NULL; w = w->w_next) 1544 { 1545 struct stat st; 1546 auto time_t submittime = 0; 1547 long dfsize; 1548 int flags = 0; 1549 int qfver; 1550 char message[MAXLINE]; 1551 char bodytype[MAXNAME + 1]; 1552 1553 printf("%8s", w->w_name + 2); 1554 f = fopen(w->w_name, "r"); 1555 if (f == NULL) 1556 { 1557 printf(" (job completed)\n"); 1558 errno = 0; 1559 continue; 1560 } 1561 w->w_name[0] = 'd'; 1562 if (stat(w->w_name, &st) >= 0) 1563 dfsize = st.st_size; 1564 else 1565 dfsize = -1; 1566 if (w->w_lock) 1567 printf("*"); 1568 else if (shouldqueue(w->w_pri, w->w_ctime)) 1569 printf("X"); 1570 else 1571 printf(" "); 1572 errno = 0; 1573 1574 message[0] = bodytype[0] = '\0'; 1575 qfver = 0; 1576 while (fgets(buf, sizeof buf, f) != NULL) 1577 { 1578 register int i; 1579 register char *p; 1580 1581 fixcrlf(buf, TRUE); 1582 switch (buf[0]) 1583 { 1584 case 'V': /* queue file version */ 1585 qfver = atoi(&buf[1]); 1586 break; 1587 1588 case 'M': /* error message */ 1589 if ((i = strlen(&buf[1])) >= sizeof message) 1590 i = sizeof message - 1; 1591 bcopy(&buf[1], message, i); 1592 message[i] = '\0'; 1593 break; 1594 1595 case 'B': /* body type */ 1596 if ((i = strlen(&buf[1])) >= sizeof bodytype) 1597 i = sizeof bodytype - 1; 1598 bcopy(&buf[1], bodytype, i); 1599 bodytype[i] = '\0'; 1600 break; 1601 1602 case 'S': /* sender name */ 1603 if (Verbose) 1604 printf("%8ld %10ld%c%.12s %.38s", 1605 dfsize, 1606 w->w_pri, 1607 bitset(EF_WARNING, flags) ? '+' : ' ', 1608 ctime(&submittime) + 4, 1609 &buf[1]); 1610 else 1611 printf("%8ld %.16s %.45s", dfsize, 1612 ctime(&submittime), &buf[1]); 1613 if (message[0] != '\0' || bodytype[0] != '\0') 1614 { 1615 printf("\n %10.10s", bodytype); 1616 if (message[0] != '\0') 1617 printf(" (%.60s)", message); 1618 } 1619 break; 1620 1621 case 'C': /* controlling user */ 1622 if (Verbose) 1623 printf("\n\t\t\t\t (---%.34s---)", 1624 &buf[1]); 1625 break; 1626 1627 case 'R': /* recipient name */ 1628 p = &buf[1]; 1629 if (qfver >= 1) 1630 { 1631 p = strchr(p, ':'); 1632 if (p == NULL) 1633 break; 1634 p++; 1635 } 1636 if (Verbose) 1637 printf("\n\t\t\t\t\t %.38s", p); 1638 else 1639 printf("\n\t\t\t\t %.45s", p); 1640 break; 1641 1642 case 'T': /* creation time */ 1643 submittime = atol(&buf[1]); 1644 break; 1645 1646 case 'F': /* flag bits */ 1647 for (p = &buf[1]; *p != '\0'; p++) 1648 { 1649 switch (*p) 1650 { 1651 case 'w': 1652 flags |= EF_WARNING; 1653 break; 1654 } 1655 } 1656 } 1657 } 1658 if (submittime == (time_t) 0) 1659 printf(" (no control file)"); 1660 printf("\n"); 1661 (void) fclose(f); 1662 } 1663 } 1664 1665 # endif /* QUEUE */ 1666 /* 1667 ** QUEUENAME -- build a file name in the queue directory for this envelope. 1668 ** 1669 ** Assigns an id code if one does not already exist. 1670 ** This code is very careful to avoid trashing existing files 1671 ** under any circumstances. 1672 ** 1673 ** Parameters: 1674 ** e -- envelope to build it in/from. 1675 ** type -- the file type, used as the first character 1676 ** of the file name. 1677 ** 1678 ** Returns: 1679 ** a pointer to the new file name (in a static buffer). 1680 ** 1681 ** Side Effects: 1682 ** If no id code is already assigned, queuename will 1683 ** assign an id code, create a qf file, and leave a 1684 ** locked, open-for-write file pointer in the envelope. 1685 */ 1686 1687 char * 1688 queuename(e, type) 1689 register ENVELOPE *e; 1690 int type; 1691 { 1692 static int pid = -1; 1693 static char c0; 1694 static char c1; 1695 static char c2; 1696 time_t now; 1697 struct tm *tm; 1698 static char buf[MAXNAME + 1]; 1699 1700 if (e->e_id == NULL) 1701 { 1702 char qf[20]; 1703 1704 /* find a unique id */ 1705 if (pid != getpid()) 1706 { 1707 /* new process -- start back at "AA" */ 1708 pid = getpid(); 1709 now = curtime(); 1710 tm = localtime(&now); 1711 c0 = 'A' + tm->tm_hour; 1712 c1 = 'A'; 1713 c2 = 'A' - 1; 1714 } 1715 (void) sprintf(qf, "qf%cAA%05d", c0, pid); 1716 1717 while (c1 < '~' || c2 < 'Z') 1718 { 1719 int i; 1720 1721 if (c2 >= 'Z') 1722 { 1723 c1++; 1724 c2 = 'A' - 1; 1725 } 1726 qf[3] = c1; 1727 qf[4] = ++c2; 1728 if (tTd(7, 20)) 1729 printf("queuename: trying \"%s\"\n", qf); 1730 1731 i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode); 1732 if (i < 0) 1733 { 1734 if (errno == EEXIST) 1735 continue; 1736 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 1737 qf, QueueDir, geteuid()); 1738 exit(EX_UNAVAILABLE); 1739 } 1740 if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB)) 1741 { 1742 e->e_lockfp = fdopen(i, "w"); 1743 break; 1744 } 1745 1746 /* a reader got the file; abandon it and try again */ 1747 (void) close(i); 1748 } 1749 if (c1 >= '~' && c2 >= 'Z') 1750 { 1751 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 1752 qf, QueueDir, geteuid()); 1753 exit(EX_OSERR); 1754 } 1755 e->e_id = newstr(&qf[2]); 1756 define('i', e->e_id, e); 1757 if (tTd(7, 1)) 1758 printf("queuename: assigned id %s, env=%x\n", e->e_id, e); 1759 if (tTd(7, 9)) 1760 { 1761 printf(" lockfd="); 1762 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 1763 } 1764 # ifdef LOG 1765 if (LogLevel > 93) 1766 syslog(LOG_DEBUG, "%s: assigned id", e->e_id); 1767 # endif /* LOG */ 1768 } 1769 1770 if (type == '\0') 1771 return (NULL); 1772 (void) sprintf(buf, "%cf%s", type, e->e_id); 1773 if (tTd(7, 2)) 1774 printf("queuename: %s\n", buf); 1775 return (buf); 1776 } 1777 /* 1778 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 1779 ** 1780 ** Parameters: 1781 ** e -- the envelope to unlock. 1782 ** 1783 ** Returns: 1784 ** none 1785 ** 1786 ** Side Effects: 1787 ** unlocks the queue for `e'. 1788 */ 1789 1790 unlockqueue(e) 1791 ENVELOPE *e; 1792 { 1793 if (tTd(51, 4)) 1794 printf("unlockqueue(%s)\n", e->e_id); 1795 1796 /* if there is a lock file in the envelope, close it */ 1797 if (e->e_lockfp != NULL) 1798 xfclose(e->e_lockfp, "unlockqueue", e->e_id); 1799 e->e_lockfp = NULL; 1800 1801 /* don't create a queue id if we don't already have one */ 1802 if (e->e_id == NULL) 1803 return; 1804 1805 /* remove the transcript */ 1806 # ifdef LOG 1807 if (LogLevel > 87) 1808 syslog(LOG_DEBUG, "%s: unlock", e->e_id); 1809 # endif /* LOG */ 1810 if (!tTd(51, 104)) 1811 xunlink(queuename(e, 'x')); 1812 1813 } 1814 /* 1815 ** SETCTLUSER -- create a controlling address 1816 ** 1817 ** Create a fake "address" given only a local login name; this is 1818 ** used as a "controlling user" for future recipient addresses. 1819 ** 1820 ** Parameters: 1821 ** user -- the user name of the controlling user. 1822 ** 1823 ** Returns: 1824 ** An address descriptor for the controlling user. 1825 ** 1826 ** Side Effects: 1827 ** none. 1828 */ 1829 1830 ADDRESS * 1831 setctluser(user) 1832 char *user; 1833 { 1834 register ADDRESS *a; 1835 struct passwd *pw; 1836 char *p; 1837 1838 /* 1839 ** See if this clears our concept of controlling user. 1840 */ 1841 1842 if (user == NULL || *user == '\0') 1843 return NULL; 1844 1845 /* 1846 ** Set up addr fields for controlling user. 1847 */ 1848 1849 a = (ADDRESS *) xalloc(sizeof *a); 1850 bzero((char *) a, sizeof *a); 1851 1852 p = strchr(user, ':'); 1853 if (p != NULL) 1854 *p++ = '\0'; 1855 if (*user != '\0' && (pw = getpwnam(user)) != NULL) 1856 { 1857 if (strcmp(pw->pw_dir, "/") == 0) 1858 a->q_home = ""; 1859 else 1860 a->q_home = newstr(pw->pw_dir); 1861 a->q_uid = pw->pw_uid; 1862 a->q_gid = pw->pw_gid; 1863 a->q_flags |= QGOODUID; 1864 } 1865 1866 if (*user != '\0') 1867 a->q_user = newstr(user); 1868 else if (p != NULL) 1869 a->q_user = newstr(p); 1870 else 1871 a->q_user = newstr(DefUser); 1872 1873 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 1874 a->q_mailer = LocalMailer; 1875 if (p == NULL) 1876 a->q_paddr = a->q_user; 1877 else 1878 a->q_paddr = newstr(p); 1879 return a; 1880 } 1881 /* 1882 ** LOSEQFILE -- save the qf as Qf and try to let someone know 1883 ** 1884 ** Parameters: 1885 ** e -- the envelope (e->e_id will be used). 1886 ** why -- reported to whomever can hear. 1887 ** 1888 ** Returns: 1889 ** none. 1890 */ 1891 1892 void 1893 loseqfile(e, why) 1894 register ENVELOPE *e; 1895 char *why; 1896 { 1897 char *p; 1898 char buf[40]; 1899 1900 if (e == NULL || e->e_id == NULL) 1901 return; 1902 if (strlen(e->e_id) > sizeof buf - 4) 1903 return; 1904 strcpy(buf, queuename(e, 'q')); 1905 p = queuename(e, 'Q'); 1906 if (rename(buf, p) < 0) 1907 syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid()); 1908 #ifdef LOG 1909 else if (LogLevel > 0) 1910 syslog(LOG_ALERT, "Losing %s: %s", buf, why); 1911 #endif 1912 } 1913