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