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