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