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