1 /* 2 ** Sendmail 3 ** Copyright (c) 1983 Eric P. Allman 4 ** Berkeley, California 5 ** 6 ** Copyright (c) 1983 Regents of the University of California. 7 ** All rights reserved. The Berkeley software License Agreement 8 ** specifies the terms and conditions for redistribution. 9 */ 10 11 #ifndef lint 12 static char SccsId[] = "@(#)conf.c 5.1 (Berkeley) 06/07/85"; 13 #endif not lint 14 15 # include <pwd.h> 16 # include <sys/ioctl.h> 17 # include "sendmail.h" 18 19 /* 20 ** CONF.C -- Sendmail Configuration Tables. 21 ** 22 ** Defines the configuration of this installation. 23 ** 24 ** Compilation Flags: 25 ** V6 -- running on a version 6 system. This determines 26 ** whether to define certain routines between 27 ** the two systems. If you are running a funny 28 ** system, e.g., V6 with long tty names, this 29 ** should be checked carefully. 30 ** VMUNIX -- running on a Berkeley UNIX system. 31 ** 32 ** Configuration Variables: 33 ** HdrInfo -- a table describing well-known header fields. 34 ** Each entry has the field name and some flags, 35 ** which are described in sendmail.h. 36 ** 37 ** Notes: 38 ** I have tried to put almost all the reasonable 39 ** configuration information into the configuration 40 ** file read at runtime. My intent is that anything 41 ** here is a function of the version of UNIX you 42 ** are running, or is really static -- for example 43 ** the headers are a superset of widely used 44 ** protocols. If you find yourself playing with 45 ** this file too much, you may be making a mistake! 46 */ 47 48 49 50 51 SCCSID(@(#)conf.c 5.1 06/07/85); 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 "sender", H_FROM, 71 "from", H_FROM, 72 "full-name", H_ACHECK, 73 "return-receipt-to", H_FROM, 74 "errors-to", H_FROM, 75 /* destination fields */ 76 "to", H_RCPT, 77 "resent-to", H_RCPT|H_RESENT, 78 "cc", H_RCPT, 79 "resent-cc", H_RCPT|H_RESENT, 80 "bcc", H_RCPT|H_ACHECK, 81 "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 82 /* message identification and control */ 83 "message-id", 0, 84 "resent-message-id", H_RESENT, 85 "message", H_EOH, 86 "text", H_EOH, 87 /* date fields */ 88 "date", 0, 89 "resent-date", H_RESENT, 90 /* trace fields */ 91 "received", H_TRACE|H_FORCE, 92 "via", H_TRACE|H_FORCE, 93 "mail-from", H_TRACE|H_FORCE, 94 95 NULL, 0, 96 }; 97 98 99 /* 100 ** ARPANET error message numbers. 101 */ 102 103 char Arpa_Info[] = "050"; /* arbitrary info */ 104 char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 105 char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 106 char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 107 108 109 110 /* 111 ** Location of system files/databases/etc. 112 */ 113 114 char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */ 115 char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */ 116 117 118 119 /* 120 ** Some other configuration.... 121 */ 122 123 char SpaceSub; /* character to replace <lwsp> in addrs */ 124 int QueueLA; /* load avg > QueueLA -> just queue */ 125 int RefuseLA; /* load avg > RefuseLA -> refuse connections */ 126 127 # ifdef V6 128 /* 129 ** TTYNAME -- return name of terminal. 130 ** 131 ** Parameters: 132 ** fd -- file descriptor to check. 133 ** 134 ** Returns: 135 ** pointer to full path of tty. 136 ** NULL if no tty. 137 ** 138 ** Side Effects: 139 ** none. 140 */ 141 142 char * 143 ttyname(fd) 144 int fd; 145 { 146 register char tn; 147 static char pathn[] = "/dev/ttyx"; 148 149 /* compute the pathname of the controlling tty */ 150 if ((tn = ttyn(fd)) == NULL) 151 { 152 errno = 0; 153 return (NULL); 154 } 155 pathn[8] = tn; 156 return (pathn); 157 } 158 /* 159 ** FDOPEN -- Open a stdio file given an open file descriptor. 160 ** 161 ** This is included here because it is standard in v7, but we 162 ** need it in v6. 163 ** 164 ** Algorithm: 165 ** Open /dev/null to create a descriptor. 166 ** Close that descriptor. 167 ** Copy the existing fd into the descriptor. 168 ** 169 ** Parameters: 170 ** fd -- the open file descriptor. 171 ** type -- "r", "w", or whatever. 172 ** 173 ** Returns: 174 ** The file descriptor it creates. 175 ** 176 ** Side Effects: 177 ** none 178 ** 179 ** Called By: 180 ** deliver 181 ** 182 ** Notes: 183 ** The mode of fd must match "type". 184 */ 185 186 FILE * 187 fdopen(fd, type) 188 int fd; 189 char *type; 190 { 191 register FILE *f; 192 193 f = fopen("/dev/null", type); 194 (void) close(fileno(f)); 195 fileno(f) = fd; 196 return (f); 197 } 198 /* 199 ** INDEX -- Return pointer to character in string 200 ** 201 ** For V7 compatibility. 202 ** 203 ** Parameters: 204 ** s -- a string to scan. 205 ** c -- a character to look for. 206 ** 207 ** Returns: 208 ** If c is in s, returns the address of the first 209 ** instance of c in s. 210 ** NULL if c is not in s. 211 ** 212 ** Side Effects: 213 ** none. 214 */ 215 216 char * 217 index(s, c) 218 register char *s; 219 register char c; 220 { 221 while (*s != '\0') 222 { 223 if (*s++ == c) 224 return (--s); 225 } 226 return (NULL); 227 } 228 /* 229 ** UMASK -- fake the umask system call. 230 ** 231 ** Since V6 always acts like the umask is zero, we will just 232 ** assume the same thing. 233 */ 234 235 /*ARGSUSED*/ 236 umask(nmask) 237 { 238 return (0); 239 } 240 241 242 /* 243 ** GETRUID -- get real user id. 244 */ 245 246 getruid() 247 { 248 return (getuid() & 0377); 249 } 250 251 252 /* 253 ** GETRGID -- get real group id. 254 */ 255 256 getrgid() 257 { 258 return (getgid() & 0377); 259 } 260 261 262 /* 263 ** GETEUID -- get effective user id. 264 */ 265 266 geteuid() 267 { 268 return ((getuid() >> 8) & 0377); 269 } 270 271 272 /* 273 ** GETEGID -- get effective group id. 274 */ 275 276 getegid() 277 { 278 return ((getgid() >> 8) & 0377); 279 } 280 281 # endif V6 282 283 # ifndef V6 284 285 /* 286 ** GETRUID -- get real user id (V7) 287 */ 288 289 getruid() 290 { 291 if (OpMode == MD_DAEMON) 292 return (RealUid); 293 else 294 return (getuid()); 295 } 296 297 298 /* 299 ** GETRGID -- get real group id (V7). 300 */ 301 302 getrgid() 303 { 304 if (OpMode == MD_DAEMON) 305 return (RealGid); 306 else 307 return (getgid()); 308 } 309 310 # endif V6 311 /* 312 ** USERNAME -- return the user id of the logged in user. 313 ** 314 ** Parameters: 315 ** none. 316 ** 317 ** Returns: 318 ** The login name of the logged in user. 319 ** 320 ** Side Effects: 321 ** none. 322 ** 323 ** Notes: 324 ** The return value is statically allocated. 325 */ 326 327 char * 328 username() 329 { 330 static char *myname = NULL; 331 extern char *getlogin(); 332 register struct passwd *pw; 333 extern struct passwd *getpwuid(); 334 335 /* cache the result */ 336 if (myname == NULL) 337 { 338 myname = getlogin(); 339 if (myname == NULL || myname[0] == '\0') 340 { 341 342 pw = getpwuid(getruid()); 343 if (pw != NULL) 344 myname = pw->pw_name; 345 } 346 else 347 { 348 349 pw = getpwnam(myname); 350 if(getuid() != pw->pw_uid) 351 { 352 pw = getpwuid(getuid()); 353 myname = pw->pw_name; 354 } 355 } 356 if (myname == NULL || myname[0] == '\0') 357 { 358 syserr("Who are you?"); 359 myname = "postmaster"; 360 } 361 } 362 363 return (myname); 364 } 365 /* 366 ** TTYPATH -- Get the path of the user's tty 367 ** 368 ** Returns the pathname of the user's tty. Returns NULL if 369 ** the user is not logged in or if s/he has write permission 370 ** denied. 371 ** 372 ** Parameters: 373 ** none 374 ** 375 ** Returns: 376 ** pathname of the user's tty. 377 ** NULL if not logged in or write permission denied. 378 ** 379 ** Side Effects: 380 ** none. 381 ** 382 ** WARNING: 383 ** Return value is in a local buffer. 384 ** 385 ** Called By: 386 ** savemail 387 */ 388 389 # include <sys/stat.h> 390 391 char * 392 ttypath() 393 { 394 struct stat stbuf; 395 register char *pathn; 396 extern char *ttyname(); 397 extern char *getlogin(); 398 399 /* compute the pathname of the controlling tty */ 400 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 401 (pathn = ttyname(0)) == NULL) 402 { 403 errno = 0; 404 return (NULL); 405 } 406 407 /* see if we have write permission */ 408 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 409 { 410 errno = 0; 411 return (NULL); 412 } 413 414 /* see if the user is logged in */ 415 if (getlogin() == NULL) 416 return (NULL); 417 418 /* looks good */ 419 return (pathn); 420 } 421 /* 422 ** CHECKCOMPAT -- check for From and To person compatible. 423 ** 424 ** This routine can be supplied on a per-installation basis 425 ** to determine whether a person is allowed to send a message. 426 ** This allows restriction of certain types of internet 427 ** forwarding or registration of users. 428 ** 429 ** If the hosts are found to be incompatible, an error 430 ** message should be given using "usrerr" and FALSE should 431 ** be returned. 432 ** 433 ** 'NoReturn' can be set to suppress the return-to-sender 434 ** function; this should be done on huge messages. 435 ** 436 ** Parameters: 437 ** to -- the person being sent to. 438 ** 439 ** Returns: 440 ** TRUE -- ok to send. 441 ** FALSE -- not ok. 442 ** 443 ** Side Effects: 444 ** none (unless you include the usrerr stuff) 445 */ 446 447 bool 448 checkcompat(to) 449 register ADDRESS *to; 450 { 451 # ifdef lint 452 if (to == NULL) 453 to++; 454 # endif lint 455 # ifdef EXAMPLE_CODE 456 /* this code is intended as an example only */ 457 register STAB *s; 458 459 s = stab("arpa", ST_MAILER, ST_FIND); 460 if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 461 to->q_mailer == s->s_mailer) 462 { 463 usrerr("No ARPA mail through this machine: see your system administration"); 464 /* NoReturn = TRUE; to supress return copy */ 465 return (FALSE); 466 } 467 # endif EXAMPLE_CODE 468 return (TRUE); 469 } 470 /* 471 ** HOLDSIGS -- arrange to hold all signals 472 ** 473 ** Parameters: 474 ** none. 475 ** 476 ** Returns: 477 ** none. 478 ** 479 ** Side Effects: 480 ** Arranges that signals are held. 481 */ 482 483 holdsigs() 484 { 485 } 486 /* 487 ** RLSESIGS -- arrange to release all signals 488 ** 489 ** This undoes the effect of holdsigs. 490 ** 491 ** Parameters: 492 ** none. 493 ** 494 ** Returns: 495 ** none. 496 ** 497 ** Side Effects: 498 ** Arranges that signals are released. 499 */ 500 501 rlsesigs() 502 { 503 } 504 /* 505 ** GETLA -- get the current load average 506 ** 507 ** This code stolen from la.c. 508 ** 509 ** Parameters: 510 ** none. 511 ** 512 ** Returns: 513 ** The current load average as an integer. 514 ** 515 ** Side Effects: 516 ** none. 517 */ 518 519 #ifdef VMUNIX 520 521 #include <nlist.h> 522 523 struct nlist Nl[] = 524 { 525 { "_avenrun" }, 526 #define X_AVENRUN 0 527 { 0 }, 528 }; 529 530 getla() 531 { 532 static int kmem = -1; 533 double avenrun[3]; 534 535 if (kmem < 0) 536 { 537 kmem = open("/dev/kmem", 0); 538 if (kmem < 0) 539 return (-1); 540 (void) ioctl(kmem, FIOCLEX, 0); 541 nlist("/vmunix", Nl); 542 if (Nl[0].n_type == 0) 543 return (-1); 544 } 545 if (lseek(kmem, (long) Nl[X_AVENRUN].n_value, 0) < 0 || 546 read(kmem, avenrun, sizeof(avenrun)) < sizeof(avenrun)) 547 { 548 /* thank you Ian */ 549 return (-1); 550 } 551 return ((int) (avenrun[0] + 0.5)); 552 } 553 554 #else VMUNIX 555 556 getla() 557 { 558 return (0); 559 } 560 561 #endif VMUNIX 562 /* 563 ** DBMCLOSE -- close the DBM file 564 ** 565 ** This depends on the implementation of the DBM library. It 566 ** seems to work for all versions that I have come across. 567 ** 568 ** Parameters: 569 ** none. 570 ** 571 ** Returns: 572 ** none. 573 ** 574 ** Side Effects: 575 ** Closes the current DBM file; dbminit must be 576 ** called again to continue using the DBM routines. 577 */ 578 579 dbmclose() 580 { 581 extern int pagf, dirf; /* defined in the DBM package */ 582 583 (void) close(pagf); 584 (void) close(dirf); 585 } 586