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.26 (Berkeley) 06/01/90"; 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 extern struct passwd *getpwuid(); 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 #ifndef sun 404 405 getla() 406 { 407 double avenrun[3]; 408 409 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 410 return (0); 411 return ((int) (avenrun[0] + 0.5)); 412 } 413 414 #else /* sun */ 415 416 #include <nlist.h> 417 418 struct nlist Nl[] = 419 { 420 { "_avenrun" }, 421 #define X_AVENRUN 0 422 { 0 }, 423 }; 424 425 426 extern int la; 427 428 getla() 429 { 430 static int kmem = -1; 431 long avenrun[3]; 432 extern off_t lseek(); 433 434 if (kmem < 0) 435 { 436 kmem = open("/dev/kmem", 0, 0); 437 if (kmem < 0) 438 return (-1); 439 (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 440 nlist("/vmunix", Nl); 441 if (Nl[0].n_type == 0) 442 return (-1); 443 } 444 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 445 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 446 { 447 /* thank you Ian */ 448 return (-1); 449 } 450 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 451 } 452 453 #endif /* sun */ 454 /* 455 ** SHOULDQUEUE -- should this message be queued or sent? 456 ** 457 ** Compares the message cost to the load average to decide. 458 ** 459 ** Parameters: 460 ** pri -- the priority of the message in question. 461 ** 462 ** Returns: 463 ** TRUE -- if this message should be queued up for the 464 ** time being. 465 ** FALSE -- if the load is low enough to send this message. 466 ** 467 ** Side Effects: 468 ** none. 469 */ 470 471 bool 472 shouldqueue(pri) 473 long pri; 474 { 475 if (la < QueueLA) 476 return (FALSE); 477 return (pri > (QueueFactor / (la - QueueLA + 1))); 478 } 479 /* 480 ** SETPROCTITLE -- set process title for ps 481 ** 482 ** Parameters: 483 ** fmt -- a printf style format string. 484 ** a, b, c -- possible parameters to fmt. 485 ** 486 ** Returns: 487 ** none. 488 ** 489 ** Side Effects: 490 ** Clobbers argv of our main procedure so ps(1) will 491 ** display the title. 492 */ 493 494 /*VARARGS1*/ 495 setproctitle(fmt, a, b, c) 496 char *fmt; 497 { 498 # ifdef SETPROCTITLE 499 register char *p; 500 register int i; 501 extern char **Argv; 502 extern char *LastArgv; 503 char buf[MAXLINE]; 504 505 (void) sprintf(buf, fmt, a, b, c); 506 507 /* make ps print "(sendmail)" */ 508 p = Argv[0]; 509 *p++ = '-'; 510 511 i = strlen(buf); 512 if (i > LastArgv - p - 2) 513 { 514 i = LastArgv - p - 2; 515 buf[i] = '\0'; 516 } 517 (void) strcpy(p, buf); 518 p += i; 519 while (p < LastArgv) 520 *p++ = ' '; 521 # endif SETPROCTITLE 522 } 523 /* 524 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 525 ** 526 ** Parameters: 527 ** none. 528 ** 529 ** Returns: 530 ** none. 531 ** 532 ** Side Effects: 533 ** Picks up extant zombies. 534 */ 535 536 # ifdef VMUNIX 537 # include <sys/wait.h> 538 # endif VMUNIX 539 540 reapchild() 541 { 542 # ifdef WNOHANG 543 union wait status; 544 545 while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 546 continue; 547 # else WNOHANG 548 auto int status; 549 550 while (wait(&status) > 0) 551 continue; 552 # endif WNOHANG 553 } 554