|
|
1.1 ! root 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.14 (Berkeley) 1/10/86"; ! 13: #endif not lint ! 14: ! 15: # include <pwd.h> ! 16: # include <sys/ioctl.h> ! 17: # ifdef sun ! 18: # include <sys/param.h> ! 19: # endif sun ! 20: # include "sendmail.h" ! 21: ! 22: /* ! 23: ** CONF.C -- Sendmail Configuration Tables. ! 24: ** ! 25: ** Defines the configuration of this installation. ! 26: ** ! 27: ** Compilation Flags: ! 28: ** V6 -- running on a version 6 system. This determines ! 29: ** whether to define certain routines between ! 30: ** the two systems. If you are running a funny ! 31: ** system, e.g., V6 with long tty names, this ! 32: ** should be checked carefully. ! 33: ** VMUNIX -- running on a Berkeley UNIX system. ! 34: ** ! 35: ** Configuration Variables: ! 36: ** HdrInfo -- a table describing well-known header fields. ! 37: ** Each entry has the field name and some flags, ! 38: ** which are described in sendmail.h. ! 39: ** ! 40: ** Notes: ! 41: ** I have tried to put almost all the reasonable ! 42: ** configuration information into the configuration ! 43: ** file read at runtime. My intent is that anything ! 44: ** here is a function of the version of UNIX you ! 45: ** are running, or is really static -- for example ! 46: ** the headers are a superset of widely used ! 47: ** protocols. If you find yourself playing with ! 48: ** this file too much, you may be making a mistake! ! 49: */ ! 50: ! 51: ! 52: ! 53: ! 54: /* ! 55: ** Header info table ! 56: ** Final (null) entry contains the flags used for any other field. ! 57: ** ! 58: ** Not all of these are actually handled specially by sendmail ! 59: ** at this time. They are included as placeholders, to let ! 60: ** you know that "someday" I intend to have sendmail do ! 61: ** something with them. ! 62: */ ! 63: ! 64: struct hdrinfo HdrInfo[] = ! 65: { ! 66: /* originator fields, most to least significant */ ! 67: "resent-sender", H_FROM|H_RESENT, ! 68: "resent-from", H_FROM|H_RESENT, ! 69: "resent-reply-to", H_FROM|H_RESENT, ! 70: "sender", H_FROM, ! 71: "from", H_FROM, ! 72: "reply-to", H_FROM, ! 73: "full-name", H_ACHECK, ! 74: "return-receipt-to", H_FROM, ! 75: "errors-to", H_FROM, ! 76: /* destination fields */ ! 77: "to", H_RCPT, ! 78: "resent-to", H_RCPT|H_RESENT, ! 79: "cc", H_RCPT, ! 80: "resent-cc", H_RCPT|H_RESENT, ! 81: "bcc", H_RCPT|H_ACHECK, ! 82: "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, ! 83: /* message identification and control */ ! 84: "message-id", 0, ! 85: "resent-message-id", H_RESENT, ! 86: "message", H_EOH, ! 87: "text", H_EOH, ! 88: /* date fields */ ! 89: "date", 0, ! 90: "resent-date", H_RESENT, ! 91: /* trace fields */ ! 92: "received", H_TRACE|H_FORCE, ! 93: "via", H_TRACE|H_FORCE, ! 94: "mail-from", H_TRACE|H_FORCE, ! 95: ! 96: NULL, 0, ! 97: }; ! 98: ! 99: ! 100: /* ! 101: ** ARPANET error message numbers. ! 102: */ ! 103: ! 104: char Arpa_Info[] = "050"; /* arbitrary info */ ! 105: char Arpa_TSyserr[] = "451"; /* some (transient) system error */ ! 106: char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ ! 107: char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ ! 108: ! 109: ! 110: ! 111: /* ! 112: ** Location of system files/databases/etc. ! 113: */ ! 114: ! 115: char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */ ! 116: char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */ ! 117: ! 118: ! 119: ! 120: /* ! 121: ** Miscellaneous stuff. ! 122: */ ! 123: ! 124: int DtableSize = 50; /* max open files; reset in 4.2bsd */ ! 125: /* ! 126: ** SETDEFAULTS -- set default values ! 127: ** ! 128: ** Because of the way freezing is done, these must be initialized ! 129: ** using direct code. ! 130: ** ! 131: ** Parameters: ! 132: ** none. ! 133: ** ! 134: ** Returns: ! 135: ** none. ! 136: ** ! 137: ** Side Effects: ! 138: ** Initializes a bunch of global variables to their ! 139: ** default values. ! 140: */ ! 141: ! 142: setdefaults() ! 143: { ! 144: QueueLA = 8; ! 145: QueueFactor = 10000; ! 146: RefuseLA = 12; ! 147: SpaceSub = ' '; ! 148: WkRecipFact = 1000; ! 149: WkClassFact = 1800; ! 150: WkTimeFact = 9000; ! 151: FileMode = 0644; ! 152: DefUid = 1; ! 153: DefGid = 1; ! 154: } ! 155: ! 156: # ifdef V6 ! 157: /* ! 158: ** TTYNAME -- return name of terminal. ! 159: ** ! 160: ** Parameters: ! 161: ** fd -- file descriptor to check. ! 162: ** ! 163: ** Returns: ! 164: ** pointer to full path of tty. ! 165: ** NULL if no tty. ! 166: ** ! 167: ** Side Effects: ! 168: ** none. ! 169: */ ! 170: ! 171: char * ! 172: ttyname(fd) ! 173: int fd; ! 174: { ! 175: register char tn; ! 176: static char pathn[] = "/dev/ttyx"; ! 177: ! 178: /* compute the pathname of the controlling tty */ ! 179: if ((tn = ttyn(fd)) == NULL) ! 180: { ! 181: errno = 0; ! 182: return (NULL); ! 183: } ! 184: pathn[8] = tn; ! 185: return (pathn); ! 186: } ! 187: /* ! 188: ** FDOPEN -- Open a stdio file given an open file descriptor. ! 189: ** ! 190: ** This is included here because it is standard in v7, but we ! 191: ** need it in v6. ! 192: ** ! 193: ** Algorithm: ! 194: ** Open /dev/null to create a descriptor. ! 195: ** Close that descriptor. ! 196: ** Copy the existing fd into the descriptor. ! 197: ** ! 198: ** Parameters: ! 199: ** fd -- the open file descriptor. ! 200: ** type -- "r", "w", or whatever. ! 201: ** ! 202: ** Returns: ! 203: ** The file descriptor it creates. ! 204: ** ! 205: ** Side Effects: ! 206: ** none ! 207: ** ! 208: ** Called By: ! 209: ** deliver ! 210: ** ! 211: ** Notes: ! 212: ** The mode of fd must match "type". ! 213: */ ! 214: ! 215: FILE * ! 216: fdopen(fd, type) ! 217: int fd; ! 218: char *type; ! 219: { ! 220: register FILE *f; ! 221: ! 222: f = fopen("/dev/null", type); ! 223: (void) close(fileno(f)); ! 224: fileno(f) = fd; ! 225: return (f); ! 226: } ! 227: /* ! 228: ** INDEX -- Return pointer to character in string ! 229: ** ! 230: ** For V7 compatibility. ! 231: ** ! 232: ** Parameters: ! 233: ** s -- a string to scan. ! 234: ** c -- a character to look for. ! 235: ** ! 236: ** Returns: ! 237: ** If c is in s, returns the address of the first ! 238: ** instance of c in s. ! 239: ** NULL if c is not in s. ! 240: ** ! 241: ** Side Effects: ! 242: ** none. ! 243: */ ! 244: ! 245: char * ! 246: index(s, c) ! 247: register char *s; ! 248: register char c; ! 249: { ! 250: while (*s != '\0') ! 251: { ! 252: if (*s++ == c) ! 253: return (--s); ! 254: } ! 255: return (NULL); ! 256: } ! 257: /* ! 258: ** UMASK -- fake the umask system call. ! 259: ** ! 260: ** Since V6 always acts like the umask is zero, we will just ! 261: ** assume the same thing. ! 262: */ ! 263: ! 264: /*ARGSUSED*/ ! 265: umask(nmask) ! 266: { ! 267: return (0); ! 268: } ! 269: ! 270: ! 271: /* ! 272: ** GETRUID -- get real user id. ! 273: */ ! 274: ! 275: getruid() ! 276: { ! 277: return (getuid() & 0377); ! 278: } ! 279: ! 280: ! 281: /* ! 282: ** GETRGID -- get real group id. ! 283: */ ! 284: ! 285: getrgid() ! 286: { ! 287: return (getgid() & 0377); ! 288: } ! 289: ! 290: ! 291: /* ! 292: ** GETEUID -- get effective user id. ! 293: */ ! 294: ! 295: geteuid() ! 296: { ! 297: return ((getuid() >> 8) & 0377); ! 298: } ! 299: ! 300: ! 301: /* ! 302: ** GETEGID -- get effective group id. ! 303: */ ! 304: ! 305: getegid() ! 306: { ! 307: return ((getgid() >> 8) & 0377); ! 308: } ! 309: ! 310: # endif V6 ! 311: ! 312: # ifndef V6 ! 313: ! 314: /* ! 315: ** GETRUID -- get real user id (V7) ! 316: */ ! 317: ! 318: getruid() ! 319: { ! 320: if (OpMode == MD_DAEMON) ! 321: return (RealUid); ! 322: else ! 323: return (getuid()); ! 324: } ! 325: ! 326: ! 327: /* ! 328: ** GETRGID -- get real group id (V7). ! 329: */ ! 330: ! 331: getrgid() ! 332: { ! 333: if (OpMode == MD_DAEMON) ! 334: return (RealGid); ! 335: else ! 336: return (getgid()); ! 337: } ! 338: ! 339: # endif V6 ! 340: /* ! 341: ** USERNAME -- return the user id of the logged in user. ! 342: ** ! 343: ** Parameters: ! 344: ** none. ! 345: ** ! 346: ** Returns: ! 347: ** The login name of the logged in user. ! 348: ** ! 349: ** Side Effects: ! 350: ** none. ! 351: ** ! 352: ** Notes: ! 353: ** The return value is statically allocated. ! 354: */ ! 355: ! 356: char * ! 357: username() ! 358: { ! 359: static char *myname = NULL; ! 360: extern char *getlogin(); ! 361: register struct passwd *pw; ! 362: extern struct passwd *getpwuid(); ! 363: ! 364: /* cache the result */ ! 365: if (myname == NULL) ! 366: { ! 367: myname = getlogin(); ! 368: if (myname == NULL || myname[0] == '\0') ! 369: { ! 370: ! 371: pw = getpwuid(getruid()); ! 372: if (pw != NULL) ! 373: myname = pw->pw_name; ! 374: } ! 375: else ! 376: { ! 377: ! 378: pw = getpwnam(myname); ! 379: if(getuid() != pw->pw_uid) ! 380: { ! 381: pw = getpwuid(getuid()); ! 382: if (pw != NULL) ! 383: myname = pw->pw_name; ! 384: } ! 385: } ! 386: if (myname == NULL || myname[0] == '\0') ! 387: { ! 388: syserr("Who are you?"); ! 389: myname = "postmaster"; ! 390: } ! 391: } ! 392: ! 393: return (myname); ! 394: } ! 395: /* ! 396: ** TTYPATH -- Get the path of the user's tty ! 397: ** ! 398: ** Returns the pathname of the user's tty. Returns NULL if ! 399: ** the user is not logged in or if s/he has write permission ! 400: ** denied. ! 401: ** ! 402: ** Parameters: ! 403: ** none ! 404: ** ! 405: ** Returns: ! 406: ** pathname of the user's tty. ! 407: ** NULL if not logged in or write permission denied. ! 408: ** ! 409: ** Side Effects: ! 410: ** none. ! 411: ** ! 412: ** WARNING: ! 413: ** Return value is in a local buffer. ! 414: ** ! 415: ** Called By: ! 416: ** savemail ! 417: */ ! 418: ! 419: # include <sys/stat.h> ! 420: ! 421: char * ! 422: ttypath() ! 423: { ! 424: struct stat stbuf; ! 425: register char *pathn; ! 426: extern char *ttyname(); ! 427: extern char *getlogin(); ! 428: ! 429: /* compute the pathname of the controlling tty */ ! 430: if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && ! 431: (pathn = ttyname(0)) == NULL) ! 432: { ! 433: errno = 0; ! 434: return (NULL); ! 435: } ! 436: ! 437: /* see if we have write permission */ ! 438: if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) ! 439: { ! 440: errno = 0; ! 441: return (NULL); ! 442: } ! 443: ! 444: /* see if the user is logged in */ ! 445: if (getlogin() == NULL) ! 446: return (NULL); ! 447: ! 448: /* looks good */ ! 449: return (pathn); ! 450: } ! 451: /* ! 452: ** CHECKCOMPAT -- check for From and To person compatible. ! 453: ** ! 454: ** This routine can be supplied on a per-installation basis ! 455: ** to determine whether a person is allowed to send a message. ! 456: ** This allows restriction of certain types of internet ! 457: ** forwarding or registration of users. ! 458: ** ! 459: ** If the hosts are found to be incompatible, an error ! 460: ** message should be given using "usrerr" and FALSE should ! 461: ** be returned. ! 462: ** ! 463: ** 'NoReturn' can be set to suppress the return-to-sender ! 464: ** function; this should be done on huge messages. ! 465: ** ! 466: ** Parameters: ! 467: ** to -- the person being sent to. ! 468: ** ! 469: ** Returns: ! 470: ** TRUE -- ok to send. ! 471: ** FALSE -- not ok. ! 472: ** ! 473: ** Side Effects: ! 474: ** none (unless you include the usrerr stuff) ! 475: */ ! 476: ! 477: bool ! 478: checkcompat(to) ! 479: register ADDRESS *to; ! 480: { ! 481: # ifdef lint ! 482: if (to == NULL) ! 483: to++; ! 484: # endif lint ! 485: # ifdef EXAMPLE_CODE ! 486: /* this code is intended as an example only */ ! 487: register STAB *s; ! 488: ! 489: s = stab("arpa", ST_MAILER, ST_FIND); ! 490: if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && ! 491: to->q_mailer == s->s_mailer) ! 492: { ! 493: usrerr("No ARPA mail through this machine: see your system administration"); ! 494: /* NoReturn = TRUE; to supress return copy */ ! 495: return (FALSE); ! 496: } ! 497: # endif EXAMPLE_CODE ! 498: return (TRUE); ! 499: } ! 500: /* ! 501: ** HOLDSIGS -- arrange to hold all signals ! 502: ** ! 503: ** Parameters: ! 504: ** none. ! 505: ** ! 506: ** Returns: ! 507: ** none. ! 508: ** ! 509: ** Side Effects: ! 510: ** Arranges that signals are held. ! 511: */ ! 512: ! 513: holdsigs() ! 514: { ! 515: } ! 516: /* ! 517: ** RLSESIGS -- arrange to release all signals ! 518: ** ! 519: ** This undoes the effect of holdsigs. ! 520: ** ! 521: ** Parameters: ! 522: ** none. ! 523: ** ! 524: ** Returns: ! 525: ** none. ! 526: ** ! 527: ** Side Effects: ! 528: ** Arranges that signals are released. ! 529: */ ! 530: ! 531: rlsesigs() ! 532: { ! 533: } ! 534: /* ! 535: ** GETLA -- get the current load average ! 536: ** ! 537: ** This code stolen from la.c. ! 538: ** ! 539: ** Parameters: ! 540: ** none. ! 541: ** ! 542: ** Returns: ! 543: ** The current load average as an integer. ! 544: ** ! 545: ** Side Effects: ! 546: ** none. ! 547: */ ! 548: ! 549: #ifdef VMUNIX ! 550: ! 551: #include <nlist.h> ! 552: ! 553: struct nlist Nl[] = ! 554: { ! 555: { "_avenrun" }, ! 556: #define X_AVENRUN 0 ! 557: { 0 }, ! 558: }; ! 559: ! 560: getla() ! 561: { ! 562: static int kmem = -1; ! 563: # ifdef sun ! 564: long avenrun[3]; ! 565: # else ! 566: double avenrun[3]; ! 567: # endif ! 568: extern off_t lseek(); ! 569: ! 570: if (kmem < 0) ! 571: { ! 572: kmem = open("/dev/kmem", 0, 0); ! 573: if (kmem < 0) ! 574: return (-1); ! 575: (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); ! 576: nlist("/vmunix", Nl); ! 577: if (Nl[0].n_type == 0) ! 578: return (-1); ! 579: } ! 580: if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || ! 581: read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) ! 582: { ! 583: /* thank you Ian */ ! 584: return (-1); ! 585: } ! 586: # ifdef sun ! 587: return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); ! 588: # else ! 589: return ((int) (avenrun[0] + 0.5)); ! 590: # endif ! 591: } ! 592: ! 593: #else VMUNIX ! 594: ! 595: getla() ! 596: { ! 597: return (0); ! 598: } ! 599: ! 600: #endif VMUNIX ! 601: /* ! 602: ** SHOULDQUEUE -- should this message be queued or sent? ! 603: ** ! 604: ** Compares the message cost to the load average to decide. ! 605: ** ! 606: ** Parameters: ! 607: ** pri -- the priority of the message in question. ! 608: ** ! 609: ** Returns: ! 610: ** TRUE -- if this message should be queued up for the ! 611: ** time being. ! 612: ** FALSE -- if the load is low enough to send this message. ! 613: ** ! 614: ** Side Effects: ! 615: ** none. ! 616: */ ! 617: ! 618: bool ! 619: shouldqueue(pri) ! 620: long pri; ! 621: { ! 622: int la; ! 623: ! 624: la = getla(); ! 625: if (la < QueueLA) ! 626: return (FALSE); ! 627: return (pri > (QueueFactor / (la - QueueLA + 1))); ! 628: } ! 629: /* ! 630: ** SETPROCTITLE -- set process title for ps ! 631: ** ! 632: ** Parameters: ! 633: ** fmt -- a printf style format string. ! 634: ** a, b, c -- possible parameters to fmt. ! 635: ** ! 636: ** Returns: ! 637: ** none. ! 638: ** ! 639: ** Side Effects: ! 640: ** Clobbers argv of our main procedure so ps(1) will ! 641: ** display the title. ! 642: */ ! 643: ! 644: /*VARARGS1*/ ! 645: setproctitle(fmt, a, b, c) ! 646: char *fmt; ! 647: { ! 648: # ifdef SETPROCTITLE ! 649: register char *p; ! 650: register int i; ! 651: extern char **Argv; ! 652: extern char *LastArgv; ! 653: char buf[MAXLINE]; ! 654: ! 655: (void) sprintf(buf, fmt, a, b, c); ! 656: ! 657: /* make ps print "(sendmail)" */ ! 658: p = Argv[0]; ! 659: *p++ = '-'; ! 660: ! 661: i = strlen(buf); ! 662: if (i > LastArgv - p - 2) ! 663: { ! 664: i = LastArgv - p - 2; ! 665: buf[i] = '\0'; ! 666: } ! 667: (void) strcpy(p, buf); ! 668: p += i; ! 669: while (p < LastArgv) ! 670: *p++ = ' '; ! 671: # endif SETPROCTITLE ! 672: } ! 673: /* ! 674: ** REAPCHILD -- pick up the body of my child, lest it become a zombie ! 675: ** ! 676: ** Parameters: ! 677: ** none. ! 678: ** ! 679: ** Returns: ! 680: ** none. ! 681: ** ! 682: ** Side Effects: ! 683: ** Picks up extant zombies. ! 684: */ ! 685: ! 686: # ifdef VMUNIX ! 687: # include <sys/wait.h> ! 688: # endif VMUNIX ! 689: ! 690: reapchild() ! 691: { ! 692: # ifdef WNOHANG ! 693: union wait status; ! 694: ! 695: while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) ! 696: continue; ! 697: # else WNOHANG ! 698: auto int status; ! 699: ! 700: while (wait(&status) > 0) ! 701: continue; ! 702: # endif WNOHANG ! 703: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.