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