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.20 (Berkeley) 05/29/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 #ifndef sun 392 393 getla() 394 { 395 double avenrun[3]; 396 397 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 398 return (0); 399 return ((int) (avenrun[0] + 0.5)); 400 } 401 402 #else /* sun */ 403 404 #include <nlist.h> 405 406 struct nlist Nl[] = 407 { 408 { "_avenrun" }, 409 #define X_AVENRUN 0 410 { 0 }, 411 }; 412 413 getla() 414 { 415 static int kmem = -1; 416 long avenrun[3]; 417 extern off_t lseek(); 418 419 if (kmem < 0) 420 { 421 kmem = open("/dev/kmem", 0, 0); 422 if (kmem < 0) 423 return (-1); 424 (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 425 nlist("/vmunix", Nl); 426 if (Nl[0].n_type == 0) 427 return (-1); 428 } 429 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 430 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 431 { 432 /* thank you Ian */ 433 return (-1); 434 } 435 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 436 } 437 438 #endif /* sun */ 439 /* 440 ** SHOULDQUEUE -- should this message be queued or sent? 441 ** 442 ** Compares the message cost to the load average to decide. 443 ** 444 ** Parameters: 445 ** pri -- the priority of the message in question. 446 ** 447 ** Returns: 448 ** TRUE -- if this message should be queued up for the 449 ** time being. 450 ** FALSE -- if the load is low enough to send this message. 451 ** 452 ** Side Effects: 453 ** none. 454 */ 455 456 bool 457 shouldqueue(pri) 458 long pri; 459 { 460 int la; 461 462 la = getla(); 463 if (la < QueueLA) 464 return (FALSE); 465 return (pri > (QueueFactor / (la - QueueLA + 1))); 466 } 467 /* 468 ** SETPROCTITLE -- set process title for ps 469 ** 470 ** Parameters: 471 ** fmt -- a printf style format string. 472 ** a, b, c -- possible parameters to fmt. 473 ** 474 ** Returns: 475 ** none. 476 ** 477 ** Side Effects: 478 ** Clobbers argv of our main procedure so ps(1) will 479 ** display the title. 480 */ 481 482 /*VARARGS1*/ 483 setproctitle(fmt, a, b, c) 484 char *fmt; 485 { 486 # ifdef SETPROCTITLE 487 register char *p; 488 register int i; 489 extern char **Argv; 490 extern char *LastArgv; 491 char buf[MAXLINE]; 492 493 (void) sprintf(buf, fmt, a, b, c); 494 495 /* make ps print "(sendmail)" */ 496 p = Argv[0]; 497 *p++ = '-'; 498 499 i = strlen(buf); 500 if (i > LastArgv - p - 2) 501 { 502 i = LastArgv - p - 2; 503 buf[i] = '\0'; 504 } 505 (void) strcpy(p, buf); 506 p += i; 507 while (p < LastArgv) 508 *p++ = ' '; 509 # endif SETPROCTITLE 510 } 511 /* 512 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 513 ** 514 ** Parameters: 515 ** none. 516 ** 517 ** Returns: 518 ** none. 519 ** 520 ** Side Effects: 521 ** Picks up extant zombies. 522 */ 523 524 # ifdef VMUNIX 525 # include <sys/wait.h> 526 # endif VMUNIX 527 528 reapchild() 529 { 530 # ifdef WNOHANG 531 union wait status; 532 533 while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 534 continue; 535 # else WNOHANG 536 auto int status; 537 538 while (wait(&status) > 0) 539 continue; 540 # endif WNOHANG 541 } 542