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.37 (Berkeley) 07/11/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) 408 register ADDRESS *to; 409 { 410 # ifdef lint 411 if (to == NULL) 412 to++; 413 # endif lint 414 # ifdef EXAMPLE_CODE 415 /* this code is intended as an example only */ 416 register STAB *s; 417 418 s = stab("arpa", ST_MAILER, ST_FIND); 419 if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 420 to->q_mailer == s->s_mailer) 421 { 422 usrerr("No ARPA mail through this machine: see your system administration"); 423 /* NoReturn = TRUE; to supress return copy */ 424 return (FALSE); 425 } 426 # endif EXAMPLE_CODE 427 return (TRUE); 428 } 429 /* 430 ** HOLDSIGS -- arrange to hold all signals 431 ** 432 ** Parameters: 433 ** none. 434 ** 435 ** Returns: 436 ** none. 437 ** 438 ** Side Effects: 439 ** Arranges that signals are held. 440 */ 441 442 holdsigs() 443 { 444 } 445 /* 446 ** RLSESIGS -- arrange to release all signals 447 ** 448 ** This undoes the effect of holdsigs. 449 ** 450 ** Parameters: 451 ** none. 452 ** 453 ** Returns: 454 ** none. 455 ** 456 ** Side Effects: 457 ** Arranges that signals are released. 458 */ 459 460 rlsesigs() 461 { 462 } 463 /* 464 ** GETLA -- get the current load average 465 ** 466 ** This code stolen from la.c. 467 ** 468 ** Parameters: 469 ** none. 470 ** 471 ** Returns: 472 ** The current load average as an integer. 473 ** 474 ** Side Effects: 475 ** none. 476 */ 477 478 /* try to guess what style of load average we have */ 479 #define LA_ZERO 1 /* always return load average as zero */ 480 #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 481 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 482 #define LA_SUBR 4 /* call getloadavg */ 483 484 #ifndef LA_TYPE 485 # if defined(sun) 486 # define LA_TYPE LA_INT 487 # endif 488 # if defined(mips) 489 /* Ultrix or RISC/os */ 490 # define LA_TYPE LA_INT 491 # define LA_AVENRUN "avenrun" 492 # endif 493 # if defined(hpux) 494 # define LA_TYPE LA_FLOAT 495 # endif 496 # if defined(BSD) 497 # define LA_TYPE LA_SUBR 498 # endif 499 500 # ifndef LA_TYPE 501 # define LA_TYPE LA_ZERO 502 # endif 503 #endif 504 505 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 506 507 #include <nlist.h> 508 #include <fcntl.h> 509 510 #ifndef LA_AVENRUN 511 #define LA_AVENRUN "_avenrun" 512 #endif 513 514 /* _PATH_UNIX should be defined in <paths.h> */ 515 #ifndef _PATH_UNIX 516 # if defined(hpux) 517 # define _PATH_UNIX "/hp-ux" 518 # endif 519 # if defined(mips) && !defined(ultrix) 520 /* powerful RISC/os */ 521 # define _PATH_UNIX "/unix" 522 # endif 523 # ifndef _PATH_UNIX 524 # define _PATH_UNIX "/vmunix" 525 # endif 526 #endif 527 528 struct nlist Nl[] = 529 { 530 { LA_AVENRUN }, 531 #define X_AVENRUN 0 532 { 0 }, 533 }; 534 535 #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 536 # define FSHIFT 8 537 # define FSCALE (1 << FSHIFT) 538 #endif 539 540 getla() 541 { 542 static int kmem = -1; 543 #if LA_TYPE == LA_INT 544 long avenrun[3]; 545 #else 546 double avenrun[3]; 547 #endif 548 extern off_t lseek(); 549 550 if (kmem < 0) 551 { 552 kmem = open("/dev/kmem", 0, 0); 553 if (kmem < 0) 554 return (-1); 555 (void) fcntl(kmem, F_SETFD, 1); 556 nlist(_PATH_UNIX, Nl); 557 if (Nl[0].n_type == 0) 558 return (-1); 559 } 560 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 561 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 562 { 563 /* thank you Ian */ 564 return (-1); 565 } 566 #if LA_TYPE == LA_INT 567 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 568 #else 569 return ((int) (avenrun[0] + 0.5)); 570 #endif 571 } 572 573 #else 574 #if LA_TYPE == LA_SUBR 575 576 getla() 577 { 578 double avenrun[3]; 579 580 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 581 return (-1); 582 return ((int) (avenrun[0] + 0.5)); 583 } 584 585 #else 586 587 getla() 588 { 589 return (0); 590 } 591 592 #endif 593 #endif 594 /* 595 ** SHOULDQUEUE -- should this message be queued or sent? 596 ** 597 ** Compares the message cost to the load average to decide. 598 ** 599 ** Parameters: 600 ** pri -- the priority of the message in question. 601 ** 602 ** Returns: 603 ** TRUE -- if this message should be queued up for the 604 ** time being. 605 ** FALSE -- if the load is low enough to send this message. 606 ** 607 ** Side Effects: 608 ** none. 609 */ 610 611 bool 612 shouldqueue(pri) 613 long pri; 614 { 615 if (CurrentLA < QueueLA) 616 return (FALSE); 617 return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 618 } 619 /* 620 ** REFUSECONNECTIONS -- decide if connections should be refused 621 ** 622 ** Parameters: 623 ** none. 624 ** 625 ** Returns: 626 ** TRUE if incoming SMTP connections should be refused 627 ** (for now). 628 ** FALSE if we should accept new work. 629 ** 630 ** Side Effects: 631 ** none. 632 */ 633 634 bool 635 refuseconnections() 636 { 637 /* this is probably too simplistic */ 638 return (CurrentLA > RefuseLA); 639 } 640 /* 641 ** SETPROCTITLE -- set process title for ps 642 ** 643 ** Parameters: 644 ** fmt -- a printf style format string. 645 ** a, b, c -- possible parameters to fmt. 646 ** 647 ** Returns: 648 ** none. 649 ** 650 ** Side Effects: 651 ** Clobbers argv of our main procedure so ps(1) will 652 ** display the title. 653 */ 654 655 /*VARARGS1*/ 656 setproctitle(fmt, a, b, c) 657 char *fmt; 658 { 659 # ifdef SETPROCTITLE 660 register char *p; 661 register int i; 662 extern char **Argv; 663 extern char *LastArgv; 664 char buf[MAXLINE]; 665 666 (void) sprintf(buf, fmt, a, b, c); 667 668 /* make ps print "(sendmail)" */ 669 p = Argv[0]; 670 *p++ = '-'; 671 672 i = strlen(buf); 673 if (i > LastArgv - p - 2) 674 { 675 i = LastArgv - p - 2; 676 buf[i] = '\0'; 677 } 678 (void) strcpy(p, buf); 679 p += i; 680 while (p < LastArgv) 681 *p++ = ' '; 682 # endif SETPROCTITLE 683 } 684 /* 685 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 686 ** 687 ** Parameters: 688 ** none. 689 ** 690 ** Returns: 691 ** none. 692 ** 693 ** Side Effects: 694 ** Picks up extant zombies. 695 */ 696 697 # include <sys/wait.h> 698 699 void 700 reapchild() 701 { 702 # ifdef WNOHANG 703 union wait status; 704 705 while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 706 continue; 707 # else WNOHANG 708 auto int status; 709 710 while (wait((int *)&status) > 0) 711 continue; 712 # endif WNOHANG 713 } 714