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