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