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