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