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