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