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.6 (Berkeley) 09/19/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 } 147 148 # ifdef V6 149 /* 150 ** TTYNAME -- return name of terminal. 151 ** 152 ** Parameters: 153 ** fd -- file descriptor to check. 154 ** 155 ** Returns: 156 ** pointer to full path of tty. 157 ** NULL if no tty. 158 ** 159 ** Side Effects: 160 ** none. 161 */ 162 163 char * 164 ttyname(fd) 165 int fd; 166 { 167 register char tn; 168 static char pathn[] = "/dev/ttyx"; 169 170 /* compute the pathname of the controlling tty */ 171 if ((tn = ttyn(fd)) == NULL) 172 { 173 errno = 0; 174 return (NULL); 175 } 176 pathn[8] = tn; 177 return (pathn); 178 } 179 /* 180 ** FDOPEN -- Open a stdio file given an open file descriptor. 181 ** 182 ** This is included here because it is standard in v7, but we 183 ** need it in v6. 184 ** 185 ** Algorithm: 186 ** Open /dev/null to create a descriptor. 187 ** Close that descriptor. 188 ** Copy the existing fd into the descriptor. 189 ** 190 ** Parameters: 191 ** fd -- the open file descriptor. 192 ** type -- "r", "w", or whatever. 193 ** 194 ** Returns: 195 ** The file descriptor it creates. 196 ** 197 ** Side Effects: 198 ** none 199 ** 200 ** Called By: 201 ** deliver 202 ** 203 ** Notes: 204 ** The mode of fd must match "type". 205 */ 206 207 FILE * 208 fdopen(fd, type) 209 int fd; 210 char *type; 211 { 212 register FILE *f; 213 214 f = fopen("/dev/null", type); 215 (void) close(fileno(f)); 216 fileno(f) = fd; 217 return (f); 218 } 219 /* 220 ** INDEX -- Return pointer to character in string 221 ** 222 ** For V7 compatibility. 223 ** 224 ** Parameters: 225 ** s -- a string to scan. 226 ** c -- a character to look for. 227 ** 228 ** Returns: 229 ** If c is in s, returns the address of the first 230 ** instance of c in s. 231 ** NULL if c is not in s. 232 ** 233 ** Side Effects: 234 ** none. 235 */ 236 237 char * 238 index(s, c) 239 register char *s; 240 register char c; 241 { 242 while (*s != '\0') 243 { 244 if (*s++ == c) 245 return (--s); 246 } 247 return (NULL); 248 } 249 /* 250 ** UMASK -- fake the umask system call. 251 ** 252 ** Since V6 always acts like the umask is zero, we will just 253 ** assume the same thing. 254 */ 255 256 /*ARGSUSED*/ 257 umask(nmask) 258 { 259 return (0); 260 } 261 262 263 /* 264 ** GETRUID -- get real user id. 265 */ 266 267 getruid() 268 { 269 return (getuid() & 0377); 270 } 271 272 273 /* 274 ** GETRGID -- get real group id. 275 */ 276 277 getrgid() 278 { 279 return (getgid() & 0377); 280 } 281 282 283 /* 284 ** GETEUID -- get effective user id. 285 */ 286 287 geteuid() 288 { 289 return ((getuid() >> 8) & 0377); 290 } 291 292 293 /* 294 ** GETEGID -- get effective group id. 295 */ 296 297 getegid() 298 { 299 return ((getgid() >> 8) & 0377); 300 } 301 302 # endif V6 303 304 # ifndef V6 305 306 /* 307 ** GETRUID -- get real user id (V7) 308 */ 309 310 getruid() 311 { 312 if (OpMode == MD_DAEMON) 313 return (RealUid); 314 else 315 return (getuid()); 316 } 317 318 319 /* 320 ** GETRGID -- get real group id (V7). 321 */ 322 323 getrgid() 324 { 325 if (OpMode == MD_DAEMON) 326 return (RealGid); 327 else 328 return (getgid()); 329 } 330 331 # endif V6 332 /* 333 ** USERNAME -- return the user id of the logged in user. 334 ** 335 ** Parameters: 336 ** none. 337 ** 338 ** Returns: 339 ** The login name of the logged in user. 340 ** 341 ** Side Effects: 342 ** none. 343 ** 344 ** Notes: 345 ** The return value is statically allocated. 346 */ 347 348 char * 349 username() 350 { 351 static char *myname = NULL; 352 extern char *getlogin(); 353 register struct passwd *pw; 354 extern struct passwd *getpwuid(); 355 356 /* cache the result */ 357 if (myname == NULL) 358 { 359 myname = getlogin(); 360 if (myname == NULL || myname[0] == '\0') 361 { 362 363 pw = getpwuid(getruid()); 364 if (pw != NULL) 365 myname = pw->pw_name; 366 } 367 else 368 { 369 370 pw = getpwnam(myname); 371 if(getuid() != pw->pw_uid) 372 { 373 pw = getpwuid(getuid()); 374 if (pw != NULL) 375 myname = pw->pw_name; 376 } 377 } 378 if (myname == NULL || myname[0] == '\0') 379 { 380 syserr("Who are you?"); 381 myname = "postmaster"; 382 } 383 } 384 385 return (myname); 386 } 387 /* 388 ** TTYPATH -- Get the path of the user's tty 389 ** 390 ** Returns the pathname of the user's tty. Returns NULL if 391 ** the user is not logged in or if s/he has write permission 392 ** denied. 393 ** 394 ** Parameters: 395 ** none 396 ** 397 ** Returns: 398 ** pathname of the user's tty. 399 ** NULL if not logged in or write permission denied. 400 ** 401 ** Side Effects: 402 ** none. 403 ** 404 ** WARNING: 405 ** Return value is in a local buffer. 406 ** 407 ** Called By: 408 ** savemail 409 */ 410 411 # include <sys/stat.h> 412 413 char * 414 ttypath() 415 { 416 struct stat stbuf; 417 register char *pathn; 418 extern char *ttyname(); 419 extern char *getlogin(); 420 421 /* compute the pathname of the controlling tty */ 422 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 423 (pathn = ttyname(0)) == NULL) 424 { 425 errno = 0; 426 return (NULL); 427 } 428 429 /* see if we have write permission */ 430 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 431 { 432 errno = 0; 433 return (NULL); 434 } 435 436 /* see if the user is logged in */ 437 if (getlogin() == NULL) 438 return (NULL); 439 440 /* looks good */ 441 return (pathn); 442 } 443 /* 444 ** CHECKCOMPAT -- check for From and To person compatible. 445 ** 446 ** This routine can be supplied on a per-installation basis 447 ** to determine whether a person is allowed to send a message. 448 ** This allows restriction of certain types of internet 449 ** forwarding or registration of users. 450 ** 451 ** If the hosts are found to be incompatible, an error 452 ** message should be given using "usrerr" and FALSE should 453 ** be returned. 454 ** 455 ** 'NoReturn' can be set to suppress the return-to-sender 456 ** function; this should be done on huge messages. 457 ** 458 ** Parameters: 459 ** to -- the person being sent to. 460 ** 461 ** Returns: 462 ** TRUE -- ok to send. 463 ** FALSE -- not ok. 464 ** 465 ** Side Effects: 466 ** none (unless you include the usrerr stuff) 467 */ 468 469 bool 470 checkcompat(to) 471 register ADDRESS *to; 472 { 473 # ifdef lint 474 if (to == NULL) 475 to++; 476 # endif lint 477 # ifdef EXAMPLE_CODE 478 /* this code is intended as an example only */ 479 register STAB *s; 480 481 s = stab("arpa", ST_MAILER, ST_FIND); 482 if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 483 to->q_mailer == s->s_mailer) 484 { 485 usrerr("No ARPA mail through this machine: see your system administration"); 486 /* NoReturn = TRUE; to supress return copy */ 487 return (FALSE); 488 } 489 # endif EXAMPLE_CODE 490 return (TRUE); 491 } 492 /* 493 ** HOLDSIGS -- arrange to hold all signals 494 ** 495 ** Parameters: 496 ** none. 497 ** 498 ** Returns: 499 ** none. 500 ** 501 ** Side Effects: 502 ** Arranges that signals are held. 503 */ 504 505 holdsigs() 506 { 507 } 508 /* 509 ** RLSESIGS -- arrange to release all signals 510 ** 511 ** This undoes the effect of holdsigs. 512 ** 513 ** Parameters: 514 ** none. 515 ** 516 ** Returns: 517 ** none. 518 ** 519 ** Side Effects: 520 ** Arranges that signals are released. 521 */ 522 523 rlsesigs() 524 { 525 } 526 /* 527 ** GETLA -- get the current load average 528 ** 529 ** This code stolen from la.c. 530 ** 531 ** Parameters: 532 ** none. 533 ** 534 ** Returns: 535 ** The current load average as an integer. 536 ** 537 ** Side Effects: 538 ** none. 539 */ 540 541 #ifdef VMUNIX 542 543 #include <nlist.h> 544 545 struct nlist Nl[] = 546 { 547 { "_avenrun" }, 548 #define X_AVENRUN 0 549 { 0 }, 550 }; 551 552 getla() 553 { 554 static int kmem = -1; 555 # ifdef sun 556 long avenrun[3]; 557 # else 558 double avenrun[3]; 559 # endif 560 561 if (kmem < 0) 562 { 563 kmem = open("/dev/kmem", 0, 0); 564 if (kmem < 0) 565 return (-1); 566 (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 567 nlist("/vmunix", Nl); 568 if (Nl[0].n_type == 0) 569 return (-1); 570 } 571 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 572 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 573 { 574 /* thank you Ian */ 575 return (-1); 576 } 577 # ifdef sun 578 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 579 # else 580 return ((int) (avenrun[0] + 0.5)); 581 # endif 582 } 583 584 #else VMUNIX 585 586 getla() 587 { 588 return (0); 589 } 590 591 #endif VMUNIX 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 int la; 614 615 la = getla(); 616 if (la < QueueLA) 617 return (FALSE); 618 return (pri > (QueueFactor / (la - QueueLA + 1))); 619 } 620 /* 621 ** SETPROCTITLE -- set process title for ps 622 ** 623 ** Parameters: 624 ** fmt -- a printf style format string. 625 ** a, b, c -- possible parameters to fmt. 626 ** 627 ** Returns: 628 ** none. 629 ** 630 ** Side Effects: 631 ** Clobbers argv of our main procedure so ps(1) will 632 ** display the title. 633 */ 634 635 /*VARARGS1*/ 636 setproctitle(fmt, a, b, c) 637 char *fmt; 638 { 639 # ifdef SETPROCTITLE 640 register char *p; 641 extern char **Argv; 642 extern char *LastArgv; 643 644 p = Argv[0]; 645 646 /* make ps print "(sendmail)" */ 647 *p++ = '-'; 648 649 (void) sprintf(p, fmt, a, b, c); 650 p += strlen(p); 651 652 /* avoid confusing ps */ 653 while (p < LastArgv) 654 *p++ = ' '; 655 # endif SETPROCTITLE 656 } 657