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.70 (Berkeley) 03/21/95 (with queueing)"; 14 #else 15 static char sccsid[] = "@(#)queue.c 8.70 (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 (e->e_df == NULL) 159 { 160 register FILE *dfp; 161 struct stat stbuf; 162 extern putbody(); 163 164 e->e_df = queuename(e, 'd'); 165 e->e_df = newstr(e->e_df); 166 fd = open(e->e_df, 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 e->e_df, 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 bzero(&mcibuf, sizeof mcibuf); 178 mcibuf.mci_out = dfp; 179 mcibuf.mci_mailer = FileMailer; 180 (*e->e_putbody)(&mcibuf, e, NULL); 181 (void) xfclose(dfp, "queueup dfp", e->e_id); 182 e->e_putbody = putbody; 183 } 184 185 /* 186 ** Output future work requests. 187 ** Priority and creation time should be first, since 188 ** they are required by orderq. 189 */ 190 191 /* output queue version number (must be first!) */ 192 fprintf(tfp, "V%d\n", QF_VERSION); 193 194 /* output message priority */ 195 fprintf(tfp, "P%ld\n", e->e_msgpriority); 196 197 /* output creation time */ 198 fprintf(tfp, "T%ld\n", e->e_ctime); 199 200 /* output last delivery time */ 201 fprintf(tfp, "K%ld\n", e->e_dtime); 202 203 /* output number of delivery attempts */ 204 fprintf(tfp, "N%d\n", e->e_ntries); 205 206 /* output inode number of data file */ 207 /* XXX should probably include device major/minor too */ 208 if (e->e_dfino != -1) 209 fprintf(tfp, "I%d/%d/%ld\n", 210 major(e->e_dfdev), minor(e->e_dfdev), e->e_dfino); 211 212 /* output type and name of data file */ 213 if (e->e_bodytype != NULL) 214 fprintf(tfp, "B%s\n", e->e_bodytype); 215 fprintf(tfp, "D%s\n", e->e_df); 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), df=%s, uid=%d", 386 tf, qf, e->e_df, 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, df=%s\n", e->e_id, qf, e->e_df); 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 /* 699 ** Check queue name for plausibility. This handles 700 ** both old and new type ids. 701 */ 702 703 p = d->d_name + 2; 704 if (isupper(p[0]) && isupper(p[2])) 705 p += 3; 706 else if (isupper(p[1])) 707 p += 2; 708 else 709 p = d->d_name; 710 for (i = 0; isdigit(*p); p++) 711 i++; 712 if (i < 5 || *p != '\0') 713 { 714 if (Verbose) 715 printf("orderq: bogus qf name %s\n", d->d_name); 716 #ifdef LOG 717 if (LogLevel > 3) 718 syslog(LOG_CRIT, "orderq: bogus qf name %s", 719 d->d_name); 720 #endif 721 if (strlen(d->d_name) > MAXNAME) 722 d->d_name[MAXNAME] = '\0'; 723 strcpy(lbuf, d->d_name); 724 lbuf[0] = 'Q'; 725 (void) rename(d->d_name, lbuf); 726 continue; 727 } 728 729 /* yes -- open control file (if not too many files) */ 730 if (++wn >= QUEUESIZE) 731 continue; 732 733 cf = fopen(d->d_name, "r"); 734 if (cf == NULL) 735 { 736 /* this may be some random person sending hir msgs */ 737 /* syserr("orderq: cannot open %s", cbuf); */ 738 if (tTd(41, 2)) 739 printf("orderq: cannot open %s (%d)\n", 740 d->d_name, errno); 741 errno = 0; 742 wn--; 743 continue; 744 } 745 w = &wlist[wn]; 746 w->w_name = newstr(d->d_name); 747 w->w_host = NULL; 748 w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB); 749 750 /* make sure jobs in creation don't clog queue */ 751 w->w_pri = 0x7fffffff; 752 w->w_ctime = 0; 753 754 /* extract useful information */ 755 i = NEED_P | NEED_T; 756 if (QueueLimitSender != NULL) 757 i |= NEED_S; 758 if (QueueSortOrder == QS_BYHOST || QueueLimitRecipient != NULL) 759 i |= NEED_R; 760 while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) 761 { 762 extern long atol(); 763 extern bool strcontainedin(); 764 765 switch (lbuf[0]) 766 { 767 case 'P': 768 w->w_pri = atol(&lbuf[1]); 769 i &= ~NEED_P; 770 break; 771 772 case 'T': 773 w->w_ctime = atol(&lbuf[1]); 774 i &= ~NEED_T; 775 break; 776 777 case 'R': 778 if (w->w_host == NULL && 779 (p = strrchr(&lbuf[1], '@')) != NULL) 780 w->w_host = newstr(&p[1]); 781 if (QueueLimitRecipient == NULL || 782 strcontainedin(QueueLimitRecipient, &lbuf[1])) 783 i &= ~NEED_R; 784 break; 785 786 case 'S': 787 if (QueueLimitSender != NULL && 788 strcontainedin(QueueLimitSender, &lbuf[1])) 789 i &= ~NEED_S; 790 break; 791 } 792 } 793 (void) fclose(cf); 794 795 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 796 bitset(NEED_R|NEED_S, i)) 797 { 798 /* don't even bother sorting this job in */ 799 free(w->w_name); 800 if (w->w_host) 801 free(w->w_host); 802 wn--; 803 } 804 } 805 (void) closedir(f); 806 wn++; 807 808 wc = min(wn, QUEUESIZE); 809 810 if (QueueSortOrder == QS_BYHOST) 811 { 812 extern workcmpf1(); 813 extern workcmpf2(); 814 815 /* 816 ** Sort the work directory for the first time, 817 ** based on host name, lock status, and priority. 818 */ 819 820 qsort((char *) wlist, wc, sizeof *wlist, workcmpf1); 821 822 /* 823 ** If one message to host is locked, "lock" all messages 824 ** to that host. 825 */ 826 827 i = 0; 828 while (i < wc) 829 { 830 if (!wlist[i].w_lock) 831 { 832 i++; 833 continue; 834 } 835 w = &wlist[i]; 836 while (++i < wc) 837 { 838 if (wlist[i].w_host == NULL && 839 w->w_host == NULL) 840 wlist[i].w_lock = TRUE; 841 else if (wlist[i].w_host != NULL && 842 w->w_host != NULL && 843 strcmp(wlist[i].w_host, w->w_host) == 0) 844 wlist[i].w_lock = TRUE; 845 else 846 break; 847 } 848 } 849 850 /* 851 ** Sort the work directory for the second time, 852 ** based on lock status, host name, and priority. 853 */ 854 855 qsort((char *) wlist, wc, sizeof *wlist, workcmpf2); 856 } 857 else 858 { 859 extern workcmpf0(); 860 861 /* 862 ** Simple sort based on queue priority only. 863 */ 864 865 qsort((char *) wlist, wc, sizeof *wlist, workcmpf0); 866 } 867 868 /* 869 ** Convert the work list into canonical form. 870 ** Should be turning it into a list of envelopes here perhaps. 871 */ 872 873 WorkQ = NULL; 874 for (i = wc; --i >= 0; ) 875 { 876 w = (WORK *) xalloc(sizeof *w); 877 w->w_name = wlist[i].w_name; 878 w->w_host = wlist[i].w_host; 879 w->w_lock = wlist[i].w_lock; 880 w->w_pri = wlist[i].w_pri; 881 w->w_ctime = wlist[i].w_ctime; 882 w->w_next = WorkQ; 883 WorkQ = w; 884 } 885 886 if (tTd(40, 1)) 887 { 888 for (w = WorkQ; w != NULL; w = w->w_next) 889 printf("%32s: pri=%ld\n", w->w_name, w->w_pri); 890 } 891 892 return (wn); 893 } 894 /* 895 ** WORKCMPF0 -- simple priority-only compare function. 896 ** 897 ** Parameters: 898 ** a -- the first argument. 899 ** b -- the second argument. 900 ** 901 ** Returns: 902 ** -1 if a < b 903 ** 0 if a == b 904 ** +1 if a > b 905 ** 906 ** Side Effects: 907 ** none. 908 */ 909 910 workcmpf0(a, b) 911 register WORK *a; 912 register WORK *b; 913 { 914 long pa = a->w_pri; 915 long pb = b->w_pri; 916 917 if (pa == pb) 918 return 0; 919 else if (pa > pb) 920 return 1; 921 else 922 return -1; 923 } 924 /* 925 ** WORKCMPF1 -- first compare function for ordering work based on host name. 926 ** 927 ** Sorts on host name, lock status, and priority in that order. 928 ** 929 ** Parameters: 930 ** a -- the first argument. 931 ** b -- the second argument. 932 ** 933 ** Returns: 934 ** <0 if a < b 935 ** 0 if a == b 936 ** >0 if a > b 937 ** 938 ** Side Effects: 939 ** none. 940 */ 941 942 workcmpf1(a, b) 943 register WORK *a; 944 register WORK *b; 945 { 946 int i; 947 948 /* host name */ 949 if (a->w_host != NULL && b->w_host == NULL) 950 return 1; 951 else if (a->w_host == NULL && b->w_host != NULL) 952 return -1; 953 if (a->w_host != NULL && b->w_host != NULL && 954 (i = strcmp(a->w_host, b->w_host))) 955 return i; 956 957 /* lock status */ 958 if (a->w_lock != b->w_lock) 959 return b->w_lock - a->w_lock; 960 961 /* job priority */ 962 return a->w_pri - b->w_pri; 963 } 964 /* 965 ** WORKCMPF2 -- second compare function for ordering work based on host name. 966 ** 967 ** Sorts on lock status, host name, and priority in that order. 968 ** 969 ** Parameters: 970 ** a -- the first argument. 971 ** b -- the second argument. 972 ** 973 ** Returns: 974 ** <0 if a < b 975 ** 0 if a == b 976 ** >0 if a > b 977 ** 978 ** Side Effects: 979 ** none. 980 */ 981 982 workcmpf2(a, b) 983 register WORK *a; 984 register WORK *b; 985 { 986 int i; 987 988 /* lock status */ 989 if (a->w_lock != b->w_lock) 990 return a->w_lock - b->w_lock; 991 992 /* host name */ 993 if (a->w_host != NULL && b->w_host == NULL) 994 return 1; 995 else if (a->w_host == NULL && b->w_host != NULL) 996 return -1; 997 if (a->w_host != NULL && b->w_host != NULL && 998 (i = strcmp(a->w_host, b->w_host))) 999 return i; 1000 1001 /* job priority */ 1002 return a->w_pri - b->w_pri; 1003 } 1004 /* 1005 ** DOWORK -- do a work request. 1006 ** 1007 ** Parameters: 1008 ** id -- the ID of the job to run. 1009 ** forkflag -- if set, run this in background. 1010 ** requeueflag -- if set, reinstantiate the queue quickly. 1011 ** This is used when expanding aliases in the queue. 1012 ** If forkflag is also set, it doesn't wait for the 1013 ** child. 1014 ** e - the envelope in which to run it. 1015 ** 1016 ** Returns: 1017 ** process id of process that is running the queue job. 1018 ** 1019 ** Side Effects: 1020 ** The work request is satisfied if possible. 1021 */ 1022 1023 pid_t 1024 dowork(id, forkflag, requeueflag, e) 1025 char *id; 1026 bool forkflag; 1027 bool requeueflag; 1028 register ENVELOPE *e; 1029 { 1030 register pid_t pid; 1031 extern bool readqf(); 1032 1033 if (tTd(40, 1)) 1034 printf("dowork(%s)\n", id); 1035 1036 /* 1037 ** Fork for work. 1038 */ 1039 1040 if (forkflag) 1041 { 1042 pid = fork(); 1043 if (pid < 0) 1044 { 1045 syserr("dowork: cannot fork"); 1046 return 0; 1047 } 1048 else if (pid > 0) 1049 { 1050 /* parent -- clean out connection cache */ 1051 mci_flush(FALSE, NULL); 1052 } 1053 } 1054 else 1055 { 1056 pid = 0; 1057 } 1058 1059 if (pid == 0) 1060 { 1061 /* 1062 ** CHILD 1063 ** Lock the control file to avoid duplicate deliveries. 1064 ** Then run the file as though we had just read it. 1065 ** We save an idea of the temporary name so we 1066 ** can recover on interrupt. 1067 */ 1068 1069 /* set basic modes, etc. */ 1070 (void) alarm(0); 1071 clearenvelope(e, FALSE); 1072 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 1073 e->e_errormode = EM_MAIL; 1074 e->e_id = id; 1075 GrabTo = UseErrorsTo = FALSE; 1076 ExitStat = EX_OK; 1077 if (forkflag) 1078 { 1079 disconnect(1, e); 1080 OpMode = MD_DELIVER; 1081 } 1082 # ifdef LOG 1083 if (LogLevel > 76) 1084 syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id, 1085 getpid()); 1086 # endif /* LOG */ 1087 1088 /* don't use the headers from sendmail.cf... */ 1089 e->e_header = NULL; 1090 1091 /* read the queue control file -- return if locked */ 1092 if (!readqf(e)) 1093 { 1094 if (tTd(40, 4)) 1095 printf("readqf(%s) failed\n", e->e_id); 1096 if (forkflag) 1097 exit(EX_OK); 1098 else 1099 return 0; 1100 } 1101 1102 e->e_flags |= EF_INQUEUE; 1103 1104 /* if this has been tried recently, let it be */ 1105 if (e->e_ntries > 0 && (curtime() - e->e_dtime) < MinQueueAge) 1106 { 1107 char *howlong = pintvl(curtime() - e->e_dtime, TRUE); 1108 1109 e->e_flags |= EF_KEEPQUEUE; 1110 if (Verbose || tTd(40, 8)) 1111 printf("%s: too young (%s)\n", 1112 e->e_id, howlong); 1113 #ifdef LOG 1114 if (LogLevel > 19) 1115 syslog(LOG_DEBUG, "%s: too young (%s)", 1116 e->e_id, howlong); 1117 #endif 1118 } 1119 else 1120 { 1121 eatheader(e, requeueflag); 1122 1123 if (requeueflag) 1124 queueup(e, TRUE, FALSE); 1125 1126 /* do the delivery */ 1127 sendall(e, SM_DELIVER); 1128 } 1129 1130 /* finish up and exit */ 1131 if (forkflag) 1132 finis(); 1133 else 1134 dropenvelope(e); 1135 } 1136 e->e_id = NULL; 1137 return pid; 1138 } 1139 /* 1140 ** READQF -- read queue file and set up environment. 1141 ** 1142 ** Parameters: 1143 ** e -- the envelope of the job to run. 1144 ** 1145 ** Returns: 1146 ** TRUE if it successfully read the queue file. 1147 ** FALSE otherwise. 1148 ** 1149 ** Side Effects: 1150 ** The queue file is returned locked. 1151 */ 1152 1153 bool 1154 readqf(e) 1155 register ENVELOPE *e; 1156 { 1157 register FILE *qfp; 1158 ADDRESS *ctladdr; 1159 struct stat st; 1160 char *bp; 1161 int qfver = 0; 1162 register char *p; 1163 char *orcpt = NULL; 1164 char qf[20]; 1165 char buf[MAXLINE]; 1166 extern long atol(); 1167 extern ADDRESS *setctluser(); 1168 extern void loseqfile(); 1169 1170 /* 1171 ** Read and process the file. 1172 */ 1173 1174 strcpy(qf, queuename(e, 'q')); 1175 qfp = fopen(qf, "r+"); 1176 if (qfp == NULL) 1177 { 1178 if (tTd(40, 8)) 1179 printf("readqf(%s): fopen failure (%s)\n", 1180 qf, errstring(errno)); 1181 if (errno != ENOENT) 1182 syserr("readqf: no control file %s", qf); 1183 return FALSE; 1184 } 1185 1186 if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB)) 1187 { 1188 /* being processed by another queuer */ 1189 if (Verbose || tTd(40, 8)) 1190 printf("%s: locked\n", e->e_id); 1191 # ifdef LOG 1192 if (LogLevel > 19) 1193 syslog(LOG_DEBUG, "%s: locked", e->e_id); 1194 # endif /* LOG */ 1195 (void) fclose(qfp); 1196 return FALSE; 1197 } 1198 1199 /* 1200 ** Check the queue file for plausibility to avoid attacks. 1201 */ 1202 1203 if (fstat(fileno(qfp), &st) < 0) 1204 { 1205 /* must have been being processed by someone else */ 1206 if (tTd(40, 8)) 1207 printf("readqf(%s): fstat failure (%s)\n", 1208 qf, errstring(errno)); 1209 fclose(qfp); 1210 return FALSE; 1211 } 1212 1213 if (st.st_uid != geteuid()) 1214 { 1215 # ifdef LOG 1216 if (LogLevel > 0) 1217 { 1218 syslog(LOG_ALERT, "%s: bogus queue file, uid=%d, mode=%o", 1219 e->e_id, st.st_uid, st.st_mode); 1220 } 1221 # endif /* LOG */ 1222 if (tTd(40, 8)) 1223 printf("readqf(%s): bogus file\n", qf); 1224 loseqfile(e, "bogus file uid in mqueue"); 1225 fclose(qfp); 1226 return FALSE; 1227 } 1228 1229 if (st.st_size == 0) 1230 { 1231 /* must be a bogus file -- just remove it */ 1232 (void) unlink(qf); 1233 fclose(qfp); 1234 return FALSE; 1235 } 1236 1237 if (st.st_nlink == 0) 1238 { 1239 /* 1240 ** Race condition -- we got a file just as it was being 1241 ** unlinked. Just assume it is zero length. 1242 */ 1243 1244 fclose(qfp); 1245 return FALSE; 1246 } 1247 1248 /* good file -- save this lock */ 1249 e->e_lockfp = qfp; 1250 1251 /* do basic system initialization */ 1252 initsys(e); 1253 define('i', e->e_id, e); 1254 1255 LineNumber = 0; 1256 e->e_flags |= EF_GLOBALERRS; 1257 OpMode = MD_DELIVER; 1258 ctladdr = NULL; 1259 e->e_dfino = -1; 1260 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 1261 { 1262 register char *p; 1263 struct stat st; 1264 u_long qflags; 1265 ADDRESS *q; 1266 1267 if (tTd(40, 4)) 1268 printf("+++++ %s\n", bp); 1269 switch (bp[0]) 1270 { 1271 case 'V': /* queue file version number */ 1272 qfver = atoi(&bp[1]); 1273 if (qfver > QF_VERSION) 1274 { 1275 syserr("Version number in qf (%d) greater than max (%d)", 1276 qfver, QF_VERSION); 1277 } 1278 break; 1279 1280 case 'C': /* specify controlling user */ 1281 ctladdr = setctluser(&bp[1]); 1282 break; 1283 1284 case 'Q': /* original recipient */ 1285 orcpt = newstr(&bp[1]); 1286 break; 1287 1288 case 'R': /* specify recipient */ 1289 p = bp; 1290 qflags = 0; 1291 if (qfver >= 1) 1292 { 1293 /* get flag bits */ 1294 while (*++p != '\0' && *p != ':') 1295 { 1296 switch (*p) 1297 { 1298 case 'S': 1299 qflags |= QPINGONSUCCESS; 1300 break; 1301 1302 case 'F': 1303 qflags |= QPINGONFAILURE; 1304 break; 1305 1306 case 'D': 1307 qflags |= QPINGONDELAY; 1308 break; 1309 1310 case 'P': 1311 qflags |= QPRIMARY; 1312 break; 1313 } 1314 } 1315 } 1316 else 1317 qflags |= QPRIMARY; 1318 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e); 1319 if (q != NULL) 1320 { 1321 q->q_alias = ctladdr; 1322 q->q_flags |= qflags; 1323 q->q_orcpt = orcpt; 1324 (void) recipient(q, &e->e_sendqueue, 0, e); 1325 } 1326 orcpt = NULL; 1327 break; 1328 1329 case 'E': /* specify error recipient */ 1330 /* no longer used */ 1331 break; 1332 1333 case 'H': /* header */ 1334 (void) chompheader(&bp[1], FALSE, e); 1335 break; 1336 1337 case 'M': /* message */ 1338 /* ignore this; we want a new message next time */ 1339 break; 1340 1341 case 'S': /* sender */ 1342 setsender(newstr(&bp[1]), e, NULL, TRUE); 1343 break; 1344 1345 case 'B': /* body type */ 1346 e->e_bodytype = newstr(&bp[1]); 1347 break; 1348 1349 case 'D': /* data file name */ 1350 e->e_df = newstr(&bp[1]); 1351 e->e_dfp = fopen(e->e_df, "r"); 1352 if (e->e_dfp == NULL) 1353 { 1354 syserr("readqf: cannot open %s", e->e_df); 1355 e->e_msgsize = -1; 1356 } 1357 else if (fstat(fileno(e->e_dfp), &st) >= 0) 1358 { 1359 e->e_msgsize = st.st_size; 1360 e->e_dfdev = st.st_dev; 1361 e->e_dfino = st.st_ino; 1362 } 1363 break; 1364 1365 case 'T': /* init time */ 1366 e->e_ctime = atol(&bp[1]); 1367 break; 1368 1369 case 'I': /* data file's inode number */ 1370 if (e->e_dfino == -1) 1371 e->e_dfino = atol(&buf[1]); 1372 break; 1373 1374 case 'K': /* time of last deliver attempt */ 1375 e->e_dtime = atol(&buf[1]); 1376 break; 1377 1378 case 'N': /* number of delivery attempts */ 1379 e->e_ntries = atoi(&buf[1]); 1380 break; 1381 1382 case 'P': /* message priority */ 1383 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 1384 break; 1385 1386 case 'F': /* flag bits */ 1387 for (p = &bp[1]; *p != '\0'; p++) 1388 { 1389 switch (*p) 1390 { 1391 case 'w': /* warning sent */ 1392 e->e_flags |= EF_WARNING; 1393 break; 1394 1395 case 'r': /* response */ 1396 e->e_flags |= EF_RESPONSE; 1397 break; 1398 1399 case '8': /* has 8 bit data */ 1400 e->e_flags |= EF_HAS8BIT; 1401 break; 1402 } 1403 } 1404 break; 1405 1406 case 'Z': /* original envelope id from ESMTP */ 1407 e->e_envid = newstr(&bp[1]); 1408 break; 1409 1410 case '$': /* define macro */ 1411 define(bp[1], newstr(&bp[2]), e); 1412 break; 1413 1414 case '\0': /* blank line; ignore */ 1415 break; 1416 1417 default: 1418 syserr("readqf: %s: line %d: bad line \"%s\"", 1419 qf, LineNumber, bp); 1420 fclose(qfp); 1421 loseqfile(e, "unrecognized line"); 1422 return FALSE; 1423 } 1424 1425 if (bp != buf) 1426 free(bp); 1427 } 1428 1429 /* 1430 ** If we haven't read any lines, this queue file is empty. 1431 ** Arrange to remove it without referencing any null pointers. 1432 */ 1433 1434 if (LineNumber == 0) 1435 { 1436 errno = 0; 1437 e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; 1438 } 1439 return TRUE; 1440 } 1441 /* 1442 ** PRINTQUEUE -- print out a representation of the mail queue 1443 ** 1444 ** Parameters: 1445 ** none. 1446 ** 1447 ** Returns: 1448 ** none. 1449 ** 1450 ** Side Effects: 1451 ** Prints a listing of the mail queue on the standard output. 1452 */ 1453 1454 printqueue() 1455 { 1456 register WORK *w; 1457 FILE *f; 1458 int nrequests; 1459 char buf[MAXLINE]; 1460 1461 /* 1462 ** Check for permission to print the queue 1463 */ 1464 1465 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 1466 { 1467 struct stat st; 1468 # ifdef NGROUPS 1469 int n; 1470 GIDSET_T gidset[NGROUPS]; 1471 # endif 1472 1473 if (stat(QueueDir, &st) < 0) 1474 { 1475 syserr("Cannot stat %s", QueueDir); 1476 return; 1477 } 1478 # ifdef NGROUPS 1479 n = getgroups(NGROUPS, gidset); 1480 while (--n >= 0) 1481 { 1482 if (gidset[n] == st.st_gid) 1483 break; 1484 } 1485 if (n < 0) 1486 # else 1487 if (RealGid != st.st_gid) 1488 # endif 1489 { 1490 usrerr("510 You are not permitted to see the queue"); 1491 setstat(EX_NOPERM); 1492 return; 1493 } 1494 } 1495 1496 /* 1497 ** Read and order the queue. 1498 */ 1499 1500 nrequests = orderq(TRUE); 1501 1502 /* 1503 ** Print the work list that we have read. 1504 */ 1505 1506 /* first see if there is anything */ 1507 if (nrequests <= 0) 1508 { 1509 printf("Mail queue is empty\n"); 1510 return; 1511 } 1512 1513 CurrentLA = getla(); /* get load average */ 1514 1515 printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s"); 1516 if (nrequests > QUEUESIZE) 1517 printf(", only %d printed", QUEUESIZE); 1518 if (Verbose) 1519 printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n"); 1520 else 1521 printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); 1522 for (w = WorkQ; w != NULL; w = w->w_next) 1523 { 1524 struct stat st; 1525 auto time_t submittime = 0; 1526 long dfsize = -1; 1527 int flags = 0; 1528 int qfver; 1529 char message[MAXLINE]; 1530 char bodytype[MAXNAME + 1]; 1531 1532 printf("%8s", w->w_name + 2); 1533 f = fopen(w->w_name, "r"); 1534 if (f == NULL) 1535 { 1536 printf(" (job completed)\n"); 1537 errno = 0; 1538 continue; 1539 } 1540 if (w->w_lock) 1541 printf("*"); 1542 else if (shouldqueue(w->w_pri, w->w_ctime)) 1543 printf("X"); 1544 else 1545 printf(" "); 1546 errno = 0; 1547 1548 message[0] = bodytype[0] = '\0'; 1549 qfver = 0; 1550 while (fgets(buf, sizeof buf, f) != NULL) 1551 { 1552 register int i; 1553 register char *p; 1554 1555 fixcrlf(buf, TRUE); 1556 switch (buf[0]) 1557 { 1558 case 'V': /* queue file version */ 1559 qfver = atoi(&buf[1]); 1560 break; 1561 1562 case 'M': /* error message */ 1563 if ((i = strlen(&buf[1])) >= sizeof message) 1564 i = sizeof message - 1; 1565 bcopy(&buf[1], message, i); 1566 message[i] = '\0'; 1567 break; 1568 1569 case 'B': /* body type */ 1570 if ((i = strlen(&buf[1])) >= sizeof bodytype) 1571 i = sizeof bodytype - 1; 1572 bcopy(&buf[1], bodytype, i); 1573 bodytype[i] = '\0'; 1574 break; 1575 1576 case 'S': /* sender name */ 1577 if (Verbose) 1578 printf("%8ld %10ld%c%.12s %.38s", 1579 dfsize, 1580 w->w_pri, 1581 bitset(EF_WARNING, flags) ? '+' : ' ', 1582 ctime(&submittime) + 4, 1583 &buf[1]); 1584 else 1585 printf("%8ld %.16s %.45s", dfsize, 1586 ctime(&submittime), &buf[1]); 1587 if (message[0] != '\0' || bodytype[0] != '\0') 1588 { 1589 printf("\n %10.10s", bodytype); 1590 if (message[0] != '\0') 1591 printf(" (%.60s)", message); 1592 } 1593 break; 1594 1595 case 'C': /* controlling user */ 1596 if (Verbose) 1597 printf("\n\t\t\t\t (---%.34s---)", 1598 &buf[1]); 1599 break; 1600 1601 case 'R': /* recipient name */ 1602 p = &buf[1]; 1603 if (qfver >= 1) 1604 { 1605 p = strchr(p, ':'); 1606 if (p == NULL) 1607 break; 1608 p++; 1609 } 1610 if (Verbose) 1611 printf("\n\t\t\t\t\t %.38s", p); 1612 else 1613 printf("\n\t\t\t\t %.45s", p); 1614 break; 1615 1616 case 'T': /* creation time */ 1617 submittime = atol(&buf[1]); 1618 break; 1619 1620 case 'D': /* data file name */ 1621 if (stat(&buf[1], &st) >= 0) 1622 dfsize = st.st_size; 1623 break; 1624 1625 case 'F': /* flag bits */ 1626 for (p = &buf[1]; *p != '\0'; p++) 1627 { 1628 switch (*p) 1629 { 1630 case 'w': 1631 flags |= EF_WARNING; 1632 break; 1633 } 1634 } 1635 } 1636 } 1637 if (submittime == (time_t) 0) 1638 printf(" (no control file)"); 1639 printf("\n"); 1640 (void) fclose(f); 1641 } 1642 } 1643 1644 # endif /* QUEUE */ 1645 /* 1646 ** QUEUENAME -- build a file name in the queue directory for this envelope. 1647 ** 1648 ** Assigns an id code if one does not already exist. 1649 ** This code is very careful to avoid trashing existing files 1650 ** under any circumstances. 1651 ** 1652 ** Parameters: 1653 ** e -- envelope to build it in/from. 1654 ** type -- the file type, used as the first character 1655 ** of the file name. 1656 ** 1657 ** Returns: 1658 ** a pointer to the new file name (in a static buffer). 1659 ** 1660 ** Side Effects: 1661 ** If no id code is already assigned, queuename will 1662 ** assign an id code, create a qf file, and leave a 1663 ** locked, open-for-write file pointer in the envelope. 1664 */ 1665 1666 char * 1667 queuename(e, type) 1668 register ENVELOPE *e; 1669 int type; 1670 { 1671 static int pid = -1; 1672 static char c0; 1673 static char c1; 1674 static char c2; 1675 time_t now; 1676 struct tm *tm; 1677 static char buf[MAXNAME + 1]; 1678 1679 if (e->e_id == NULL) 1680 { 1681 char qf[20]; 1682 1683 /* find a unique id */ 1684 if (pid != getpid()) 1685 { 1686 /* new process -- start back at "AA" */ 1687 pid = getpid(); 1688 now = curtime(); 1689 tm = localtime(&now); 1690 c0 = 'A' + tm->tm_hour; 1691 c1 = 'A'; 1692 c2 = 'A' - 1; 1693 } 1694 (void) sprintf(qf, "qf%cAA%05d", c0, pid); 1695 1696 while (c1 < '~' || c2 < 'Z') 1697 { 1698 int i; 1699 1700 if (c2 >= 'Z') 1701 { 1702 c1++; 1703 c2 = 'A' - 1; 1704 } 1705 qf[3] = c1; 1706 qf[4] = ++c2; 1707 if (tTd(7, 20)) 1708 printf("queuename: trying \"%s\"\n", qf); 1709 1710 i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode); 1711 if (i < 0) 1712 { 1713 if (errno == EEXIST) 1714 continue; 1715 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 1716 qf, QueueDir, geteuid()); 1717 exit(EX_UNAVAILABLE); 1718 } 1719 if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB)) 1720 { 1721 e->e_lockfp = fdopen(i, "w"); 1722 break; 1723 } 1724 1725 /* a reader got the file; abandon it and try again */ 1726 (void) close(i); 1727 } 1728 if (c1 >= '~' && c2 >= 'Z') 1729 { 1730 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 1731 qf, QueueDir, geteuid()); 1732 exit(EX_OSERR); 1733 } 1734 e->e_id = newstr(&qf[2]); 1735 define('i', e->e_id, e); 1736 if (tTd(7, 1)) 1737 printf("queuename: assigned id %s, env=%x\n", e->e_id, e); 1738 if (tTd(7, 9)) 1739 { 1740 printf(" lockfd="); 1741 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 1742 } 1743 # ifdef LOG 1744 if (LogLevel > 93) 1745 syslog(LOG_DEBUG, "%s: assigned id", e->e_id); 1746 # endif /* LOG */ 1747 } 1748 1749 if (type == '\0') 1750 return (NULL); 1751 (void) sprintf(buf, "%cf%s", type, e->e_id); 1752 if (tTd(7, 2)) 1753 printf("queuename: %s\n", buf); 1754 return (buf); 1755 } 1756 /* 1757 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 1758 ** 1759 ** Parameters: 1760 ** e -- the envelope to unlock. 1761 ** 1762 ** Returns: 1763 ** none 1764 ** 1765 ** Side Effects: 1766 ** unlocks the queue for `e'. 1767 */ 1768 1769 unlockqueue(e) 1770 ENVELOPE *e; 1771 { 1772 if (tTd(51, 4)) 1773 printf("unlockqueue(%s)\n", e->e_id); 1774 1775 /* if there is a lock file in the envelope, close it */ 1776 if (e->e_lockfp != NULL) 1777 xfclose(e->e_lockfp, "unlockqueue", e->e_id); 1778 e->e_lockfp = NULL; 1779 1780 /* don't create a queue id if we don't already have one */ 1781 if (e->e_id == NULL) 1782 return; 1783 1784 /* remove the transcript */ 1785 # ifdef LOG 1786 if (LogLevel > 87) 1787 syslog(LOG_DEBUG, "%s: unlock", e->e_id); 1788 # endif /* LOG */ 1789 if (!tTd(51, 104)) 1790 xunlink(queuename(e, 'x')); 1791 1792 } 1793 /* 1794 ** SETCTLUSER -- create a controlling address 1795 ** 1796 ** Create a fake "address" given only a local login name; this is 1797 ** used as a "controlling user" for future recipient addresses. 1798 ** 1799 ** Parameters: 1800 ** user -- the user name of the controlling user. 1801 ** 1802 ** Returns: 1803 ** An address descriptor for the controlling user. 1804 ** 1805 ** Side Effects: 1806 ** none. 1807 */ 1808 1809 ADDRESS * 1810 setctluser(user) 1811 char *user; 1812 { 1813 register ADDRESS *a; 1814 struct passwd *pw; 1815 char *p; 1816 1817 /* 1818 ** See if this clears our concept of controlling user. 1819 */ 1820 1821 if (user == NULL || *user == '\0') 1822 return NULL; 1823 1824 /* 1825 ** Set up addr fields for controlling user. 1826 */ 1827 1828 a = (ADDRESS *) xalloc(sizeof *a); 1829 bzero((char *) a, sizeof *a); 1830 1831 p = strchr(user, ':'); 1832 if (p != NULL) 1833 *p++ = '\0'; 1834 if (*user != '\0' && (pw = getpwnam(user)) != NULL) 1835 { 1836 if (strcmp(pw->pw_dir, "/") == 0) 1837 a->q_home = ""; 1838 else 1839 a->q_home = newstr(pw->pw_dir); 1840 a->q_uid = pw->pw_uid; 1841 a->q_gid = pw->pw_gid; 1842 a->q_user = newstr(user); 1843 a->q_flags |= QGOODUID; 1844 } 1845 else 1846 { 1847 a->q_user = newstr(DefUser); 1848 } 1849 1850 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 1851 a->q_mailer = LocalMailer; 1852 if (p == NULL) 1853 a->q_paddr = a->q_user; 1854 else 1855 a->q_paddr = newstr(p); 1856 return a; 1857 } 1858 /* 1859 ** LOSEQFILE -- save the qf as Qf and try to let someone know 1860 ** 1861 ** Parameters: 1862 ** e -- the envelope (e->e_id will be used). 1863 ** why -- reported to whomever can hear. 1864 ** 1865 ** Returns: 1866 ** none. 1867 */ 1868 1869 void 1870 loseqfile(e, why) 1871 register ENVELOPE *e; 1872 char *why; 1873 { 1874 char buf[40]; 1875 1876 if (e == NULL || e->e_id == NULL) 1877 return; 1878 if (strlen(e->e_id) > sizeof buf - 4) 1879 return; 1880 strcpy(buf, queuename(e, 'q')); 1881 rename(buf, queuename(e, 'Q')); 1882 #ifdef LOG 1883 syslog(LOG_ALERT, "Losing %s: %s", buf, why); 1884 #endif 1885 } 1886