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