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