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