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