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