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