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.3.1.1 (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 myname = pw->pw_name; 375 } 376 } 377 if (myname == NULL || myname[0] == '\0') 378 { 379 syserr("Who are you?"); 380 myname = "postmaster"; 381 } 382 } 383 384 return (myname); 385 } 386 /* 387 ** TTYPATH -- Get the path of the user's tty 388 ** 389 ** Returns the pathname of the user's tty. Returns NULL if 390 ** the user is not logged in or if s/he has write permission 391 ** denied. 392 ** 393 ** Parameters: 394 ** none 395 ** 396 ** Returns: 397 ** pathname of the user's tty. 398 ** NULL if not logged in or write permission denied. 399 ** 400 ** Side Effects: 401 ** none. 402 ** 403 ** WARNING: 404 ** Return value is in a local buffer. 405 ** 406 ** Called By: 407 ** savemail 408 */ 409 410 # include <sys/stat.h> 411 412 char * 413 ttypath() 414 { 415 struct stat stbuf; 416 register char *pathn; 417 extern char *ttyname(); 418 extern char *getlogin(); 419 420 /* compute the pathname of the controlling tty */ 421 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 422 (pathn = ttyname(0)) == NULL) 423 { 424 errno = 0; 425 return (NULL); 426 } 427 428 /* see if we have write permission */ 429 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 430 { 431 errno = 0; 432 return (NULL); 433 } 434 435 /* see if the user is logged in */ 436 if (getlogin() == NULL) 437 return (NULL); 438 439 /* looks good */ 440 return (pathn); 441 } 442 /* 443 ** CHECKCOMPAT -- check for From and To person compatible. 444 ** 445 ** This routine can be supplied on a per-installation basis 446 ** to determine whether a person is allowed to send a message. 447 ** This allows restriction of certain types of internet 448 ** forwarding or registration of users. 449 ** 450 ** If the hosts are found to be incompatible, an error 451 ** message should be given using "usrerr" and FALSE should 452 ** be returned. 453 ** 454 ** 'NoReturn' can be set to suppress the return-to-sender 455 ** function; this should be done on huge messages. 456 ** 457 ** Parameters: 458 ** to -- the person being sent to. 459 ** 460 ** Returns: 461 ** TRUE -- ok to send. 462 ** FALSE -- not ok. 463 ** 464 ** Side Effects: 465 ** none (unless you include the usrerr stuff) 466 */ 467 468 bool 469 checkcompat(to) 470 register ADDRESS *to; 471 { 472 # ifdef lint 473 if (to == NULL) 474 to++; 475 # endif lint 476 # ifdef EXAMPLE_CODE 477 /* this code is intended as an example only */ 478 register STAB *s; 479 480 s = stab("arpa", ST_MAILER, ST_FIND); 481 if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 482 to->q_mailer == s->s_mailer) 483 { 484 usrerr("No ARPA mail through this machine: see your system administration"); 485 /* NoReturn = TRUE; to supress return copy */ 486 return (FALSE); 487 } 488 # endif EXAMPLE_CODE 489 return (TRUE); 490 } 491 /* 492 ** HOLDSIGS -- arrange to hold all signals 493 ** 494 ** Parameters: 495 ** none. 496 ** 497 ** Returns: 498 ** none. 499 ** 500 ** Side Effects: 501 ** Arranges that signals are held. 502 */ 503 504 holdsigs() 505 { 506 } 507 /* 508 ** RLSESIGS -- arrange to release all signals 509 ** 510 ** This undoes the effect of holdsigs. 511 ** 512 ** Parameters: 513 ** none. 514 ** 515 ** Returns: 516 ** none. 517 ** 518 ** Side Effects: 519 ** Arranges that signals are released. 520 */ 521 522 rlsesigs() 523 { 524 } 525 /* 526 ** GETLA -- get the current load average 527 ** 528 ** This code stolen from la.c. 529 ** 530 ** Parameters: 531 ** none. 532 ** 533 ** Returns: 534 ** The current load average as an integer. 535 ** 536 ** Side Effects: 537 ** none. 538 */ 539 540 #ifdef VMUNIX 541 542 #include <nlist.h> 543 544 struct nlist Nl[] = 545 { 546 { "_avenrun" }, 547 #define X_AVENRUN 0 548 { 0 }, 549 }; 550 551 getla() 552 { 553 static int kmem = -1; 554 # ifdef sun 555 long avenrun[3]; 556 # else 557 double avenrun[3]; 558 # endif 559 560 if (kmem < 0) 561 { 562 kmem = open("/dev/kmem", 0); 563 if (kmem < 0) 564 return (-1); 565 (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 566 nlist("/vmunix", Nl); 567 if (Nl[0].n_type == 0) 568 return (-1); 569 } 570 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) < 0 || 571 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 572 { 573 /* thank you Ian */ 574 return (-1); 575 } 576 # ifdef sun 577 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 578 # else 579 return ((int) (avenrun[0] + 0.5)); 580 # endif 581 } 582 583 #else VMUNIX 584 585 getla() 586 { 587 return (0); 588 } 589 590 #endif VMUNIX 591 /* 592 ** SHOULDQUEUE -- should this message be queued or sent? 593 ** 594 ** Compares the message cost to the load average to decide. 595 ** 596 ** Parameters: 597 ** pri -- the priority of the message in question. 598 ** 599 ** Returns: 600 ** TRUE -- if this message should be queued up for the 601 ** time being. 602 ** FALSE -- if the load is low enough to send this message. 603 ** 604 ** Side Effects: 605 ** none. 606 */ 607 608 bool 609 shouldqueue(pri) 610 long pri; 611 { 612 int la; 613 614 la = getla(); 615 if (la < QueueLA) 616 return (FALSE); 617 return (pri > (QueueFactor / (la - QueueLA + 1))); 618 } 619 /* 620 ** SETPROCTITLE -- set process title for ps 621 ** 622 ** Parameters: 623 ** fmt -- a printf style format string. 624 ** a, b, c -- possible parameters to fmt. 625 ** 626 ** Returns: 627 ** none. 628 ** 629 ** Side Effects: 630 ** Clobbers argv of our main procedure so ps(1) will 631 ** display the title. 632 */ 633 634 /*VARARGS1*/ 635 setproctitle(fmt, a, b, c) 636 char *fmt; 637 { 638 # ifdef SETPROCTITLE 639 register char *p; 640 extern char **Argv; 641 extern char *LastArgv; 642 643 p = Argv[0]; 644 645 /* make ps print "(sendmail)" */ 646 *p++ = '-'; 647 648 (void) sprintf(p, fmt, a, b, c); 649 p += strlen(p); 650 651 /* avoid confusing ps */ 652 while (p < LastArgv) 653 *p++ = ' '; 654 # endif SETPROCTITLE 655 } 656