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