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