1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 * 12 * Sendmail 13 * Copyright (c) 1983 Eric P. Allman 14 * Berkeley, California 15 */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)conf.c 5.15 (Berkeley) 03/13/88"; 19 #endif /* not lint */ 20 21 # include <pwd.h> 22 # include <sys/ioctl.h> 23 # ifdef sun 24 # include <sys/param.h> 25 # endif sun 26 # include "sendmail.h" 27 28 /* 29 ** CONF.C -- Sendmail Configuration Tables. 30 ** 31 ** Defines the configuration of this installation. 32 ** 33 ** Compilation Flags: 34 ** V6 -- running on a version 6 system. This determines 35 ** whether to define certain routines between 36 ** the two systems. If you are running a funny 37 ** system, e.g., V6 with long tty names, this 38 ** should be checked carefully. 39 ** VMUNIX -- running on a Berkeley UNIX system. 40 ** 41 ** Configuration Variables: 42 ** HdrInfo -- a table describing well-known header fields. 43 ** Each entry has the field name and some flags, 44 ** which are described in sendmail.h. 45 ** 46 ** Notes: 47 ** I have tried to put almost all the reasonable 48 ** configuration information into the configuration 49 ** file read at runtime. My intent is that anything 50 ** here is a function of the version of UNIX you 51 ** are running, or is really static -- for example 52 ** the headers are a superset of widely used 53 ** protocols. If you find yourself playing with 54 ** this file too much, you may be making a mistake! 55 */ 56 57 58 59 60 /* 61 ** Header info table 62 ** Final (null) entry contains the flags used for any other field. 63 ** 64 ** Not all of these are actually handled specially by sendmail 65 ** at this time. They are included as placeholders, to let 66 ** you know that "someday" I intend to have sendmail do 67 ** something with them. 68 */ 69 70 struct hdrinfo HdrInfo[] = 71 { 72 /* originator fields, most to least significant */ 73 "resent-sender", H_FROM|H_RESENT, 74 "resent-from", H_FROM|H_RESENT, 75 "resent-reply-to", H_FROM|H_RESENT, 76 "sender", H_FROM, 77 "from", H_FROM, 78 "reply-to", H_FROM, 79 "full-name", H_ACHECK, 80 "return-receipt-to", H_FROM, 81 "errors-to", H_FROM, 82 /* destination fields */ 83 "to", H_RCPT, 84 "resent-to", H_RCPT|H_RESENT, 85 "cc", H_RCPT, 86 "resent-cc", H_RCPT|H_RESENT, 87 "bcc", H_RCPT|H_ACHECK, 88 "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 89 /* message identification and control */ 90 "message-id", 0, 91 "resent-message-id", H_RESENT, 92 "message", H_EOH, 93 "text", H_EOH, 94 /* date fields */ 95 "date", 0, 96 "resent-date", H_RESENT, 97 /* trace fields */ 98 "received", H_TRACE|H_FORCE, 99 "via", H_TRACE|H_FORCE, 100 "mail-from", H_TRACE|H_FORCE, 101 102 NULL, 0, 103 }; 104 105 106 /* 107 ** ARPANET error message numbers. 108 */ 109 110 char Arpa_Info[] = "050"; /* arbitrary info */ 111 char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 112 char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 113 char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 114 115 116 117 /* 118 ** Location of system files/databases/etc. 119 */ 120 121 char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */ 122 char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */ 123 124 125 126 /* 127 ** Miscellaneous stuff. 128 */ 129 130 int DtableSize = 50; /* max open files; reset in 4.2bsd */ 131 /* 132 ** SETDEFAULTS -- set default values 133 ** 134 ** Because of the way freezing is done, these must be initialized 135 ** using direct code. 136 ** 137 ** Parameters: 138 ** none. 139 ** 140 ** Returns: 141 ** none. 142 ** 143 ** Side Effects: 144 ** Initializes a bunch of global variables to their 145 ** default values. 146 */ 147 148 setdefaults() 149 { 150 QueueLA = 8; 151 QueueFactor = 10000; 152 RefuseLA = 12; 153 SpaceSub = ' '; 154 WkRecipFact = 1000; 155 WkClassFact = 1800; 156 WkTimeFact = 9000; 157 FileMode = 0644; 158 DefUid = 1; 159 DefGid = 1; 160 } 161 162 # ifdef V6 163 /* 164 ** TTYNAME -- return name of terminal. 165 ** 166 ** Parameters: 167 ** fd -- file descriptor to check. 168 ** 169 ** Returns: 170 ** pointer to full path of tty. 171 ** NULL if no tty. 172 ** 173 ** Side Effects: 174 ** none. 175 */ 176 177 char * 178 ttyname(fd) 179 int fd; 180 { 181 register char tn; 182 static char pathn[] = "/dev/ttyx"; 183 184 /* compute the pathname of the controlling tty */ 185 if ((tn = ttyn(fd)) == NULL) 186 { 187 errno = 0; 188 return (NULL); 189 } 190 pathn[8] = tn; 191 return (pathn); 192 } 193 /* 194 ** FDOPEN -- Open a stdio file given an open file descriptor. 195 ** 196 ** This is included here because it is standard in v7, but we 197 ** need it in v6. 198 ** 199 ** Algorithm: 200 ** Open /dev/null to create a descriptor. 201 ** Close that descriptor. 202 ** Copy the existing fd into the descriptor. 203 ** 204 ** Parameters: 205 ** fd -- the open file descriptor. 206 ** type -- "r", "w", or whatever. 207 ** 208 ** Returns: 209 ** The file descriptor it creates. 210 ** 211 ** Side Effects: 212 ** none 213 ** 214 ** Called By: 215 ** deliver 216 ** 217 ** Notes: 218 ** The mode of fd must match "type". 219 */ 220 221 FILE * 222 fdopen(fd, type) 223 int fd; 224 char *type; 225 { 226 register FILE *f; 227 228 f = fopen("/dev/null", type); 229 (void) close(fileno(f)); 230 fileno(f) = fd; 231 return (f); 232 } 233 /* 234 ** INDEX -- Return pointer to character in string 235 ** 236 ** For V7 compatibility. 237 ** 238 ** Parameters: 239 ** s -- a string to scan. 240 ** c -- a character to look for. 241 ** 242 ** Returns: 243 ** If c is in s, returns the address of the first 244 ** instance of c in s. 245 ** NULL if c is not in s. 246 ** 247 ** Side Effects: 248 ** none. 249 */ 250 251 char * 252 index(s, c) 253 register char *s; 254 register char c; 255 { 256 while (*s != '\0') 257 { 258 if (*s++ == c) 259 return (--s); 260 } 261 return (NULL); 262 } 263 /* 264 ** UMASK -- fake the umask system call. 265 ** 266 ** Since V6 always acts like the umask is zero, we will just 267 ** assume the same thing. 268 */ 269 270 /*ARGSUSED*/ 271 umask(nmask) 272 { 273 return (0); 274 } 275 276 277 /* 278 ** GETRUID -- get real user id. 279 */ 280 281 getruid() 282 { 283 return (getuid() & 0377); 284 } 285 286 287 /* 288 ** GETRGID -- get real group id. 289 */ 290 291 getrgid() 292 { 293 return (getgid() & 0377); 294 } 295 296 297 /* 298 ** GETEUID -- get effective user id. 299 */ 300 301 geteuid() 302 { 303 return ((getuid() >> 8) & 0377); 304 } 305 306 307 /* 308 ** GETEGID -- get effective group id. 309 */ 310 311 getegid() 312 { 313 return ((getgid() >> 8) & 0377); 314 } 315 316 # endif V6 317 318 # ifndef V6 319 320 /* 321 ** GETRUID -- get real user id (V7) 322 */ 323 324 getruid() 325 { 326 if (OpMode == MD_DAEMON) 327 return (RealUid); 328 else 329 return (getuid()); 330 } 331 332 333 /* 334 ** GETRGID -- get real group id (V7). 335 */ 336 337 getrgid() 338 { 339 if (OpMode == MD_DAEMON) 340 return (RealGid); 341 else 342 return (getgid()); 343 } 344 345 # endif V6 346 /* 347 ** USERNAME -- return the user id of the logged in user. 348 ** 349 ** Parameters: 350 ** none. 351 ** 352 ** Returns: 353 ** The login name of the logged in user. 354 ** 355 ** Side Effects: 356 ** none. 357 ** 358 ** Notes: 359 ** The return value is statically allocated. 360 */ 361 362 char * 363 username() 364 { 365 static char *myname = NULL; 366 extern char *getlogin(); 367 register struct passwd *pw; 368 extern struct passwd *getpwuid(); 369 370 /* cache the result */ 371 if (myname == NULL) 372 { 373 myname = getlogin(); 374 if (myname == NULL || myname[0] == '\0') 375 { 376 377 pw = getpwuid(getruid()); 378 if (pw != NULL) 379 myname = pw->pw_name; 380 } 381 else 382 { 383 384 pw = getpwnam(myname); 385 if(getuid() != pw->pw_uid) 386 { 387 pw = getpwuid(getuid()); 388 if (pw != NULL) 389 myname = pw->pw_name; 390 } 391 } 392 if (myname == NULL || myname[0] == '\0') 393 { 394 syserr("Who are you?"); 395 myname = "postmaster"; 396 } 397 } 398 399 return (myname); 400 } 401 /* 402 ** TTYPATH -- Get the path of the user's tty 403 ** 404 ** Returns the pathname of the user's tty. Returns NULL if 405 ** the user is not logged in or if s/he has write permission 406 ** denied. 407 ** 408 ** Parameters: 409 ** none 410 ** 411 ** Returns: 412 ** pathname of the user's tty. 413 ** NULL if not logged in or write permission denied. 414 ** 415 ** Side Effects: 416 ** none. 417 ** 418 ** WARNING: 419 ** Return value is in a local buffer. 420 ** 421 ** Called By: 422 ** savemail 423 */ 424 425 # include <sys/stat.h> 426 427 char * 428 ttypath() 429 { 430 struct stat stbuf; 431 register char *pathn; 432 extern char *ttyname(); 433 extern char *getlogin(); 434 435 /* compute the pathname of the controlling tty */ 436 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 437 (pathn = ttyname(0)) == NULL) 438 { 439 errno = 0; 440 return (NULL); 441 } 442 443 /* see if we have write permission */ 444 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 445 { 446 errno = 0; 447 return (NULL); 448 } 449 450 /* see if the user is logged in */ 451 if (getlogin() == NULL) 452 return (NULL); 453 454 /* looks good */ 455 return (pathn); 456 } 457 /* 458 ** CHECKCOMPAT -- check for From and To person compatible. 459 ** 460 ** This routine can be supplied on a per-installation basis 461 ** to determine whether a person is allowed to send a message. 462 ** This allows restriction of certain types of internet 463 ** forwarding or registration of users. 464 ** 465 ** If the hosts are found to be incompatible, an error 466 ** message should be given using "usrerr" and FALSE should 467 ** be returned. 468 ** 469 ** 'NoReturn' can be set to suppress the return-to-sender 470 ** function; this should be done on huge messages. 471 ** 472 ** Parameters: 473 ** to -- the person being sent to. 474 ** 475 ** Returns: 476 ** TRUE -- ok to send. 477 ** FALSE -- not ok. 478 ** 479 ** Side Effects: 480 ** none (unless you include the usrerr stuff) 481 */ 482 483 bool 484 checkcompat(to) 485 register ADDRESS *to; 486 { 487 # ifdef lint 488 if (to == NULL) 489 to++; 490 # endif lint 491 # ifdef EXAMPLE_CODE 492 /* this code is intended as an example only */ 493 register STAB *s; 494 495 s = stab("arpa", ST_MAILER, ST_FIND); 496 if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 497 to->q_mailer == s->s_mailer) 498 { 499 usrerr("No ARPA mail through this machine: see your system administration"); 500 /* NoReturn = TRUE; to supress return copy */ 501 return (FALSE); 502 } 503 # endif EXAMPLE_CODE 504 return (TRUE); 505 } 506 /* 507 ** HOLDSIGS -- arrange to hold all signals 508 ** 509 ** Parameters: 510 ** none. 511 ** 512 ** Returns: 513 ** none. 514 ** 515 ** Side Effects: 516 ** Arranges that signals are held. 517 */ 518 519 holdsigs() 520 { 521 } 522 /* 523 ** RLSESIGS -- arrange to release all signals 524 ** 525 ** This undoes the effect of holdsigs. 526 ** 527 ** Parameters: 528 ** none. 529 ** 530 ** Returns: 531 ** none. 532 ** 533 ** Side Effects: 534 ** Arranges that signals are released. 535 */ 536 537 rlsesigs() 538 { 539 } 540 /* 541 ** GETLA -- get the current load average 542 ** 543 ** This code stolen from la.c. 544 ** 545 ** Parameters: 546 ** none. 547 ** 548 ** Returns: 549 ** The current load average as an integer. 550 ** 551 ** Side Effects: 552 ** none. 553 */ 554 555 #ifdef VMUNIX 556 557 #include <nlist.h> 558 559 struct nlist Nl[] = 560 { 561 { "_avenrun" }, 562 #define X_AVENRUN 0 563 { 0 }, 564 }; 565 566 getla() 567 { 568 static int kmem = -1; 569 # ifdef sun 570 long avenrun[3]; 571 # else 572 double avenrun[3]; 573 # endif 574 extern off_t lseek(); 575 576 if (kmem < 0) 577 { 578 kmem = open("/dev/kmem", 0, 0); 579 if (kmem < 0) 580 return (-1); 581 (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 582 nlist("/vmunix", Nl); 583 if (Nl[0].n_type == 0) 584 return (-1); 585 } 586 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 587 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 588 { 589 /* thank you Ian */ 590 return (-1); 591 } 592 # ifdef sun 593 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 594 # else 595 return ((int) (avenrun[0] + 0.5)); 596 # endif 597 } 598 599 #else VMUNIX 600 601 getla() 602 { 603 return (0); 604 } 605 606 #endif VMUNIX 607 /* 608 ** SHOULDQUEUE -- should this message be queued or sent? 609 ** 610 ** Compares the message cost to the load average to decide. 611 ** 612 ** Parameters: 613 ** pri -- the priority of the message in question. 614 ** 615 ** Returns: 616 ** TRUE -- if this message should be queued up for the 617 ** time being. 618 ** FALSE -- if the load is low enough to send this message. 619 ** 620 ** Side Effects: 621 ** none. 622 */ 623 624 bool 625 shouldqueue(pri) 626 long pri; 627 { 628 int la; 629 630 la = getla(); 631 if (la < QueueLA) 632 return (FALSE); 633 return (pri > (QueueFactor / (la - QueueLA + 1))); 634 } 635 /* 636 ** SETPROCTITLE -- set process title for ps 637 ** 638 ** Parameters: 639 ** fmt -- a printf style format string. 640 ** a, b, c -- possible parameters to fmt. 641 ** 642 ** Returns: 643 ** none. 644 ** 645 ** Side Effects: 646 ** Clobbers argv of our main procedure so ps(1) will 647 ** display the title. 648 */ 649 650 /*VARARGS1*/ 651 setproctitle(fmt, a, b, c) 652 char *fmt; 653 { 654 # ifdef SETPROCTITLE 655 register char *p; 656 register int i; 657 extern char **Argv; 658 extern char *LastArgv; 659 char buf[MAXLINE]; 660 661 (void) sprintf(buf, fmt, a, b, c); 662 663 /* make ps print "(sendmail)" */ 664 p = Argv[0]; 665 *p++ = '-'; 666 667 i = strlen(buf); 668 if (i > LastArgv - p - 2) 669 { 670 i = LastArgv - p - 2; 671 buf[i] = '\0'; 672 } 673 (void) strcpy(p, buf); 674 p += i; 675 while (p < LastArgv) 676 *p++ = ' '; 677 # endif SETPROCTITLE 678 } 679 /* 680 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 681 ** 682 ** Parameters: 683 ** none. 684 ** 685 ** Returns: 686 ** none. 687 ** 688 ** Side Effects: 689 ** Picks up extant zombies. 690 */ 691 692 # ifdef VMUNIX 693 # include <sys/wait.h> 694 # endif VMUNIX 695 696 reapchild() 697 { 698 # ifdef WNOHANG 699 union wait status; 700 701 while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 702 continue; 703 # else WNOHANG 704 auto int status; 705 706 while (wait(&status) > 0) 707 continue; 708 # endif WNOHANG 709 } 710