1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)conf.c 5.42 (Berkeley) 09/09/92"; 11 #endif /* not lint */ 12 13 # include <sys/ioctl.h> 14 # include <sys/param.h> 15 # include <pwd.h> 16 # include "sendmail.h" 17 # include "pathnames.h" 18 19 /* 20 ** CONF.C -- Sendmail Configuration Tables. 21 ** 22 ** Defines the configuration of this installation. 23 ** 24 ** Configuration Variables: 25 ** HdrInfo -- a table describing well-known header fields. 26 ** Each entry has the field name and some flags, 27 ** which are described in sendmail.h. 28 ** 29 ** Notes: 30 ** I have tried to put almost all the reasonable 31 ** configuration information into the configuration 32 ** file read at runtime. My intent is that anything 33 ** here is a function of the version of UNIX you 34 ** are running, or is really static -- for example 35 ** the headers are a superset of widely used 36 ** protocols. If you find yourself playing with 37 ** this file too much, you may be making a mistake! 38 */ 39 40 41 42 43 /* 44 ** Header info table 45 ** Final (null) entry contains the flags used for any other field. 46 ** 47 ** Not all of these are actually handled specially by sendmail 48 ** at this time. They are included as placeholders, to let 49 ** you know that "someday" I intend to have sendmail do 50 ** something with them. 51 */ 52 53 struct hdrinfo HdrInfo[] = 54 { 55 /* originator fields, most to least significant */ 56 "resent-sender", H_FROM|H_RESENT, 57 "resent-from", H_FROM|H_RESENT, 58 "resent-reply-to", H_FROM|H_RESENT, 59 "sender", H_FROM, 60 "from", H_FROM, 61 "reply-to", H_FROM, 62 "full-name", H_ACHECK, 63 "return-receipt-to", H_FROM, 64 "errors-to", H_FROM, 65 /* destination fields */ 66 "to", H_RCPT, 67 "resent-to", H_RCPT|H_RESENT, 68 "cc", H_RCPT, 69 "resent-cc", H_RCPT|H_RESENT, 70 "bcc", H_RCPT|H_ACHECK, 71 "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 72 "apparently-to", H_RCPT, 73 /* message identification and control */ 74 "message-id", 0, 75 "resent-message-id", H_RESENT, 76 "message", H_EOH, 77 "text", H_EOH, 78 /* date fields */ 79 "date", 0, 80 "resent-date", H_RESENT, 81 /* trace fields */ 82 "received", H_TRACE|H_FORCE, 83 "via", H_TRACE|H_FORCE, 84 "mail-from", H_TRACE|H_FORCE, 85 86 NULL, 0, 87 }; 88 89 90 /* 91 ** ARPANET error message numbers. 92 */ 93 94 char Arpa_Info[] = "050"; /* arbitrary info */ 95 char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 96 char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 97 char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 98 99 100 101 /* 102 ** Location of system files/databases/etc. 103 */ 104 105 char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 106 char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 107 108 109 110 /* 111 ** Miscellaneous stuff. 112 */ 113 114 int DtableSize = 50; /* max open files; reset in 4.2bsd */ 115 /* 116 ** SETDEFAULTS -- set default values 117 ** 118 ** Because of the way freezing is done, these must be initialized 119 ** using direct code. 120 ** 121 ** Parameters: 122 ** none. 123 ** 124 ** Returns: 125 ** none. 126 ** 127 ** Side Effects: 128 ** Initializes a bunch of global variables to their 129 ** default values. 130 */ 131 132 setdefaults() 133 { 134 QueueLA = 8; 135 QueueFactor = 10000; 136 RefuseLA = 12; 137 SpaceSub = ' '; 138 WkRecipFact = 1000; 139 WkClassFact = 1800; 140 WkTimeFact = 9000; 141 FileMode = 0644; 142 DefUid = 1; 143 DefGid = 1; 144 CheckpointInterval = 10; 145 MaxHopCount = MAXHOP; 146 SendMode = SM_FORK; 147 ErrorMode = EM_PRINT; 148 EightBit = FALSE; 149 MaxMciCache = 1; 150 MciCacheTimeout = 300; 151 setdefuser(); 152 setupmaps(); 153 } 154 155 156 /* 157 ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 158 */ 159 160 setdefuser() 161 { 162 struct passwd *defpwent; 163 164 if (DefUser != NULL) 165 free(DefUser); 166 if ((defpwent = getpwuid(DefUid)) != NULL) 167 DefUser = newstr(defpwent->pw_name); 168 else 169 DefUser = newstr("nobody"); 170 } 171 /* 172 ** SETUPMAPS -- set up map classes 173 ** 174 ** Since these are compiled in, they cannot be in the config file. 175 ** 176 */ 177 178 setupmaps() 179 { 180 register STAB *s; 181 MAPCLASS *hostmapclass; 182 extern char *maphostname(); 183 184 /* set up host name lookup map */ 185 s = stab("host", ST_MAPCLASS, ST_ENTER); 186 s->s_mapclass.map_init = NULL; 187 s->s_mapclass.map_lookup = maphostname; 188 hostmapclass = &s->s_mapclass; 189 190 s = stab("host", ST_MAP, ST_ENTER); 191 s->s_map.map_class = hostmapclass; 192 s->s_map.map_flags = MF_VALID; 193 194 /* 195 ** Set up other map classes. 196 */ 197 198 # ifdef DBM_MAP 199 /* dbm file access */ 200 { 201 extern void dbm_map_init(); 202 extern char *dbm_map_lookup(); 203 204 s = stab("dbm", ST_MAPCLASS, ST_ENTER); 205 s->s_mapclass.map_init = dbm_map_init; 206 s->s_mapclass.map_lookup = dbm_map_lookup; 207 } 208 # endif 209 210 # ifdef BTREE_MAP 211 /* new database file access -- btree files */ 212 { 213 extern void bt_map_init(); 214 extern char *bt_map_lookup(); 215 216 s = stab("btree", ST_MAPCLASS, ST_ENTER); 217 s->s_mapclass.map_init = bt_map_init; 218 s->s_mapclass.map_lookup = bt_map_lookup; 219 } 220 # endif 221 222 # ifdef HASH_MAP 223 /* new database file access -- hash files */ 224 { 225 extern void hash_map_init(); 226 extern char *hash_map_lookup(); 227 228 s = stab("hash", ST_MAPCLASS, ST_ENTER); 229 s->s_mapclass.map_init = hash_map_init; 230 s->s_mapclass.map_lookup = hash_map_lookup; 231 } 232 # endif 233 234 # ifdef USERDB_MAP 235 /* user database */ 236 { 237 extern void udb_map_init(); 238 extern char *udb_map_lookup(); 239 240 s = stab("udb", ST_MAPCLASS, ST_ENTER); 241 s->s_mapclass.map_init = udb_map_init; 242 s->s_mapclass.map_lookup = udb_map_lookup; 243 } 244 # endif 245 } 246 /* 247 ** GETRUID -- get real user id (V7) 248 */ 249 250 getruid() 251 { 252 if (OpMode == MD_DAEMON) 253 return (RealUid); 254 else 255 return (getuid()); 256 } 257 258 259 /* 260 ** GETRGID -- get real group id (V7). 261 */ 262 263 getrgid() 264 { 265 if (OpMode == MD_DAEMON) 266 return (RealGid); 267 else 268 return (getgid()); 269 } 270 /* 271 ** USERNAME -- return the user id of the logged in user. 272 ** 273 ** Parameters: 274 ** none. 275 ** 276 ** Returns: 277 ** The login name of the logged in user. 278 ** 279 ** Side Effects: 280 ** none. 281 ** 282 ** Notes: 283 ** The return value is statically allocated. 284 */ 285 286 char * 287 username() 288 { 289 static char *myname = NULL; 290 extern char *getlogin(); 291 register struct passwd *pw; 292 293 /* cache the result */ 294 if (myname == NULL) 295 { 296 myname = getlogin(); 297 if (myname == NULL || myname[0] == '\0') 298 { 299 300 pw = getpwuid(getruid()); 301 if (pw != NULL) 302 myname = newstr(pw->pw_name); 303 } 304 else 305 { 306 307 myname = newstr(myname); 308 if ((pw = getpwnam(myname)) == NULL || 309 getuid() != pw->pw_uid) 310 { 311 pw = getpwuid(getuid()); 312 if (pw != NULL) 313 myname = newstr(pw->pw_name); 314 } 315 } 316 if (myname == NULL || myname[0] == '\0') 317 { 318 syserr("Who are you?"); 319 myname = "postmaster"; 320 } 321 } 322 323 return (myname); 324 } 325 /* 326 ** TTYPATH -- Get the path of the user's tty 327 ** 328 ** Returns the pathname of the user's tty. Returns NULL if 329 ** the user is not logged in or if s/he has write permission 330 ** denied. 331 ** 332 ** Parameters: 333 ** none 334 ** 335 ** Returns: 336 ** pathname of the user's tty. 337 ** NULL if not logged in or write permission denied. 338 ** 339 ** Side Effects: 340 ** none. 341 ** 342 ** WARNING: 343 ** Return value is in a local buffer. 344 ** 345 ** Called By: 346 ** savemail 347 */ 348 349 # include <sys/stat.h> 350 351 char * 352 ttypath() 353 { 354 struct stat stbuf; 355 register char *pathn; 356 extern char *ttyname(); 357 extern char *getlogin(); 358 359 /* compute the pathname of the controlling tty */ 360 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 361 (pathn = ttyname(0)) == NULL) 362 { 363 errno = 0; 364 return (NULL); 365 } 366 367 /* see if we have write permission */ 368 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 369 { 370 errno = 0; 371 return (NULL); 372 } 373 374 /* see if the user is logged in */ 375 if (getlogin() == NULL) 376 return (NULL); 377 378 /* looks good */ 379 return (pathn); 380 } 381 /* 382 ** CHECKCOMPAT -- check for From and To person compatible. 383 ** 384 ** This routine can be supplied on a per-installation basis 385 ** to determine whether a person is allowed to send a message. 386 ** This allows restriction of certain types of internet 387 ** forwarding or registration of users. 388 ** 389 ** If the hosts are found to be incompatible, an error 390 ** message should be given using "usrerr" and FALSE should 391 ** be returned. 392 ** 393 ** 'NoReturn' can be set to suppress the return-to-sender 394 ** function; this should be done on huge messages. 395 ** 396 ** Parameters: 397 ** to -- the person being sent to. 398 ** 399 ** Returns: 400 ** TRUE -- ok to send. 401 ** FALSE -- not ok. 402 ** 403 ** Side Effects: 404 ** none (unless you include the usrerr stuff) 405 */ 406 407 bool 408 checkcompat(to, e) 409 register ADDRESS *to; 410 register ENVELOPE *e; 411 { 412 # ifdef lint 413 if (to == NULL) 414 to++; 415 # endif lint 416 # ifdef EXAMPLE_CODE 417 /* this code is intended as an example only */ 418 register STAB *s; 419 420 s = stab("arpa", ST_MAILER, ST_FIND); 421 if (s != NULL && e->e_from.q_mailer != LocalMailer && 422 to->q_mailer == s->s_mailer) 423 { 424 usrerr("No ARPA mail through this machine: see your system administration"); 425 /* NoReturn = TRUE; to supress return copy */ 426 return (FALSE); 427 } 428 # endif EXAMPLE_CODE 429 return (TRUE); 430 } 431 /* 432 ** HOLDSIGS -- arrange to hold all signals 433 ** 434 ** Parameters: 435 ** none. 436 ** 437 ** Returns: 438 ** none. 439 ** 440 ** Side Effects: 441 ** Arranges that signals are held. 442 */ 443 444 holdsigs() 445 { 446 } 447 /* 448 ** RLSESIGS -- arrange to release all signals 449 ** 450 ** This undoes the effect of holdsigs. 451 ** 452 ** Parameters: 453 ** none. 454 ** 455 ** Returns: 456 ** none. 457 ** 458 ** Side Effects: 459 ** Arranges that signals are released. 460 */ 461 462 rlsesigs() 463 { 464 } 465 /* 466 ** GETLA -- get the current load average 467 ** 468 ** This code stolen from la.c. 469 ** 470 ** Parameters: 471 ** none. 472 ** 473 ** Returns: 474 ** The current load average as an integer. 475 ** 476 ** Side Effects: 477 ** none. 478 */ 479 480 /* try to guess what style of load average we have */ 481 #define LA_ZERO 1 /* always return load average as zero */ 482 #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 483 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 484 #define LA_SUBR 4 /* call getloadavg */ 485 486 #ifndef LA_TYPE 487 # if defined(sun) 488 # define LA_TYPE LA_INT 489 # endif 490 # if defined(mips) 491 /* Ultrix or RISC/os */ 492 # define LA_TYPE LA_INT 493 # define LA_AVENRUN "avenrun" 494 # endif 495 # if defined(hpux) 496 # define LA_TYPE LA_FLOAT 497 # endif 498 # if defined(BSD) 499 # define LA_TYPE LA_SUBR 500 # endif 501 502 # ifndef LA_TYPE 503 # define LA_TYPE LA_ZERO 504 # endif 505 #endif 506 507 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 508 509 #include <nlist.h> 510 #include <fcntl.h> 511 512 #ifndef LA_AVENRUN 513 #define LA_AVENRUN "_avenrun" 514 #endif 515 516 /* _PATH_UNIX should be defined in <paths.h> */ 517 #ifndef _PATH_UNIX 518 # if defined(hpux) 519 # define _PATH_UNIX "/hp-ux" 520 # endif 521 # if defined(mips) && !defined(ultrix) 522 /* powerful RISC/os */ 523 # define _PATH_UNIX "/unix" 524 # endif 525 # ifndef _PATH_UNIX 526 # define _PATH_UNIX "/vmunix" 527 # endif 528 #endif 529 530 struct nlist Nl[] = 531 { 532 { LA_AVENRUN }, 533 #define X_AVENRUN 0 534 { 0 }, 535 }; 536 537 #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 538 # define FSHIFT 8 539 # define FSCALE (1 << FSHIFT) 540 #endif 541 542 getla() 543 { 544 static int kmem = -1; 545 #if LA_TYPE == LA_INT 546 long avenrun[3]; 547 #else 548 double avenrun[3]; 549 #endif 550 extern off_t lseek(); 551 552 if (kmem < 0) 553 { 554 kmem = open("/dev/kmem", 0, 0); 555 if (kmem < 0) 556 return (-1); 557 (void) fcntl(kmem, F_SETFD, 1); 558 nlist(_PATH_UNIX, Nl); 559 if (Nl[0].n_type == 0) 560 return (-1); 561 } 562 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 563 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 564 { 565 /* thank you Ian */ 566 return (-1); 567 } 568 #if LA_TYPE == LA_INT 569 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 570 #else 571 return ((int) (avenrun[0] + 0.5)); 572 #endif 573 } 574 575 #else 576 #if LA_TYPE == LA_SUBR 577 578 getla() 579 { 580 double avenrun[3]; 581 582 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 583 return (-1); 584 return ((int) (avenrun[0] + 0.5)); 585 } 586 587 #else 588 589 getla() 590 { 591 return (0); 592 } 593 594 #endif 595 #endif 596 /* 597 ** SHOULDQUEUE -- should this message be queued or sent? 598 ** 599 ** Compares the message cost to the load average to decide. 600 ** 601 ** Parameters: 602 ** pri -- the priority of the message in question. 603 ** 604 ** Returns: 605 ** TRUE -- if this message should be queued up for the 606 ** time being. 607 ** FALSE -- if the load is low enough to send this message. 608 ** 609 ** Side Effects: 610 ** none. 611 */ 612 613 bool 614 shouldqueue(pri) 615 long pri; 616 { 617 if (CurrentLA < QueueLA) 618 return (FALSE); 619 return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 620 } 621 /* 622 ** REFUSECONNECTIONS -- decide if connections should be refused 623 ** 624 ** Parameters: 625 ** none. 626 ** 627 ** Returns: 628 ** TRUE if incoming SMTP connections should be refused 629 ** (for now). 630 ** FALSE if we should accept new work. 631 ** 632 ** Side Effects: 633 ** none. 634 */ 635 636 bool 637 refuseconnections() 638 { 639 /* this is probably too simplistic */ 640 return (CurrentLA > RefuseLA); 641 } 642 /* 643 ** SETPROCTITLE -- set process title for ps 644 ** 645 ** Parameters: 646 ** fmt -- a printf style format string. 647 ** a, b, c -- possible parameters to fmt. 648 ** 649 ** Returns: 650 ** none. 651 ** 652 ** Side Effects: 653 ** Clobbers argv of our main procedure so ps(1) will 654 ** display the title. 655 */ 656 657 /*VARARGS1*/ 658 setproctitle(fmt, a, b, c) 659 char *fmt; 660 { 661 # ifdef SETPROCTITLE 662 register char *p; 663 register int i; 664 extern char **Argv; 665 extern char *LastArgv; 666 char buf[MAXLINE]; 667 668 p = buf; 669 670 /* print sendmail: heading for grep */ 671 (void) strcpy(p, "sendmail: "); 672 p += strlen(p); 673 674 /* print the argument string */ 675 (void) sprintf(p, fmt, a, b, c); 676 677 i = strlen(buf); 678 if (i > LastArgv - Argv[0] - 2) 679 { 680 i = LastArgv - Argv[0] - 2; 681 buf[i] = '\0'; 682 } 683 (void) strcpy(Argv[0], buf); 684 p = &Argv[0][i]; 685 while (p < LastArgv) 686 *p++ = ' '; 687 # endif SETPROCTITLE 688 } 689 /* 690 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 691 ** 692 ** Parameters: 693 ** none. 694 ** 695 ** Returns: 696 ** none. 697 ** 698 ** Side Effects: 699 ** Picks up extant zombies. 700 */ 701 702 # include <sys/wait.h> 703 704 void 705 reapchild() 706 { 707 # ifdef WNOHANG 708 union wait status; 709 710 while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 711 continue; 712 # else WNOHANG 713 auto int status; 714 715 while (wait((int *)&status) > 0) 716 continue; 717 # endif WNOHANG 718 } 719 /* 720 ** UNSETENV -- remove a variable from the environment 721 ** 722 ** Not needed on newer systems. 723 ** 724 ** Parameters: 725 ** name -- the string name of the environment variable to be 726 ** deleted from the current environment. 727 ** 728 ** Returns: 729 ** none. 730 ** 731 ** Globals: 732 ** environ -- a pointer to the current environment. 733 ** 734 ** Side Effects: 735 ** Modifies environ. 736 */ 737 738 #ifdef UNSETENV 739 740 void 741 unsetenv(name) 742 char *name; 743 { 744 extern char **environ; 745 register char **pp; 746 int len = strlen(name); 747 748 for (pp = environ; *pp != NULL; pp++) 749 { 750 if (strncmp(name, *pp, len) == 0 && 751 ((*pp)[len] == '=' || (*pp)[len] == '\0')) 752 break; 753 } 754 755 for (; *pp != NULL; pp++) 756 *pp = pp[1]; 757 } 758 759 #endif /* UNSETENV */ 760 /* 761 ** GETDTABLESIZE -- return number of file descriptors 762 ** 763 ** Only on non-BSD systems 764 ** 765 ** Parameters: 766 ** none 767 ** 768 ** Returns: 769 ** size of file descriptor table 770 ** 771 ** Side Effects: 772 ** none 773 */ 774 775 #ifdef SYSTEM5 776 777 int 778 getdtablesize() 779 { 780 return NOFILE; 781 } 782 783 #endif 784