122698Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 642825Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822698Sdist 922698Sdist #ifndef lint 10*53037Seric static char sccsid[] = "@(#)conf.c 5.35 (Berkeley) 03/20/92"; 1133728Sbostic #endif /* not lint */ 1222698Sdist 1314881Seric # include <sys/ioctl.h> 1424943Seric # include <sys/param.h> 1536928Sbostic # include <pwd.h> 163309Seric # include "sendmail.h" 1740980Sbostic # include "pathnames.h" 18404Seric 19294Seric /* 203309Seric ** CONF.C -- Sendmail Configuration Tables. 21294Seric ** 22294Seric ** Defines the configuration of this installation. 23294Seric ** 241388Seric ** Configuration Variables: 252897Seric ** HdrInfo -- a table describing well-known header fields. 262897Seric ** Each entry has the field name and some flags, 274147Seric ** which are described in sendmail.h. 284093Seric ** 294093Seric ** Notes: 304093Seric ** I have tried to put almost all the reasonable 314093Seric ** configuration information into the configuration 324093Seric ** file read at runtime. My intent is that anything 334093Seric ** here is a function of the version of UNIX you 344093Seric ** are running, or is really static -- for example 354093Seric ** the headers are a superset of widely used 364093Seric ** protocols. If you find yourself playing with 374093Seric ** this file too much, you may be making a mistake! 38294Seric */ 39294Seric 40294Seric 41294Seric 42294Seric 434437Seric /* 442897Seric ** Header info table 453057Seric ** Final (null) entry contains the flags used for any other field. 464147Seric ** 474147Seric ** Not all of these are actually handled specially by sendmail 484147Seric ** at this time. They are included as placeholders, to let 494147Seric ** you know that "someday" I intend to have sendmail do 504147Seric ** something with them. 512897Seric */ 522897Seric 532897Seric struct hdrinfo HdrInfo[] = 542897Seric { 558060Seric /* originator fields, most to least significant */ 5611417Seric "resent-sender", H_FROM|H_RESENT, 5711417Seric "resent-from", H_FROM|H_RESENT, 5825686Seric "resent-reply-to", H_FROM|H_RESENT, 599055Seric "sender", H_FROM, 609055Seric "from", H_FROM, 6125686Seric "reply-to", H_FROM, 629055Seric "full-name", H_ACHECK, 639055Seric "return-receipt-to", H_FROM, 649055Seric "errors-to", H_FROM, 658060Seric /* destination fields */ 669055Seric "to", H_RCPT, 6711417Seric "resent-to", H_RCPT|H_RESENT, 689055Seric "cc", H_RCPT, 6911417Seric "resent-cc", H_RCPT|H_RESENT, 709055Seric "bcc", H_RCPT|H_ACHECK, 7111417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 728060Seric /* message identification and control */ 7311417Seric "message-id", 0, 7411417Seric "resent-message-id", H_RESENT, 759055Seric "message", H_EOH, 769055Seric "text", H_EOH, 7711417Seric /* date fields */ 7811417Seric "date", 0, 7911417Seric "resent-date", H_RESENT, 808060Seric /* trace fields */ 819055Seric "received", H_TRACE|H_FORCE, 829055Seric "via", H_TRACE|H_FORCE, 839055Seric "mail-from", H_TRACE|H_FORCE, 848060Seric 859055Seric NULL, 0, 862897Seric }; 874166Seric 884166Seric 894166Seric /* 904166Seric ** ARPANET error message numbers. 914166Seric */ 924166Seric 937956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 947956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 957956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 967956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 974282Seric 984282Seric 994282Seric 1004282Seric /* 1014282Seric ** Location of system files/databases/etc. 1024282Seric */ 1034282Seric 10440980Sbostic char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 10540980Sbostic char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 1069039Seric 1079064Seric 1089064Seric 1099039Seric /* 11024943Seric ** Miscellaneous stuff. 1119039Seric */ 1129039Seric 11324943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 11424943Seric /* 11524943Seric ** SETDEFAULTS -- set default values 11624943Seric ** 11724943Seric ** Because of the way freezing is done, these must be initialized 11824943Seric ** using direct code. 11924943Seric ** 12024943Seric ** Parameters: 12124943Seric ** none. 12224943Seric ** 12324943Seric ** Returns: 12424943Seric ** none. 12524943Seric ** 12624943Seric ** Side Effects: 12724943Seric ** Initializes a bunch of global variables to their 12824943Seric ** default values. 12924943Seric */ 13024943Seric 13124943Seric setdefaults() 13224943Seric { 13324943Seric QueueLA = 8; 13424943Seric QueueFactor = 10000; 13524943Seric RefuseLA = 12; 13624943Seric SpaceSub = ' '; 13724981Seric WkRecipFact = 1000; 13824981Seric WkClassFact = 1800; 13925812Seric WkTimeFact = 9000; 14024981Seric FileMode = 0644; 14124981Seric DefUid = 1; 14224981Seric DefGid = 1; 14347284Seric CheckpointInterval = 10; 14451305Seric MaxHopCount = MAXHOP; 14552105Seric SendMode = SM_FORK; 14652105Seric ErrorMode = EM_PRINT; 14752106Seric EightBit = FALSE; 14840973Sbostic setdefuser(); 14924943Seric } 150294Seric 15140973Sbostic 1524326Seric /* 15340973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 15440973Sbostic */ 15540973Sbostic 15640973Sbostic setdefuser() 15740973Sbostic { 15840973Sbostic struct passwd *defpwent; 15940973Sbostic 16040973Sbostic if (DefUser != NULL) 16140973Sbostic free(DefUser); 16240973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 16340973Sbostic DefUser = newstr(defpwent->pw_name); 16440973Sbostic else 16540973Sbostic DefUser = newstr("nobody"); 16640973Sbostic } 16740973Sbostic 16840973Sbostic 16940973Sbostic /* 1704326Seric ** GETRUID -- get real user id (V7) 1714326Seric */ 1724326Seric 1734326Seric getruid() 1744326Seric { 1759274Seric if (OpMode == MD_DAEMON) 1764536Seric return (RealUid); 1774536Seric else 1784536Seric return (getuid()); 1794326Seric } 1804326Seric 1814326Seric 1824326Seric /* 1834326Seric ** GETRGID -- get real group id (V7). 1844326Seric */ 1854326Seric 1864326Seric getrgid() 1874326Seric { 1889274Seric if (OpMode == MD_DAEMON) 1894536Seric return (RealGid); 1904536Seric else 1914536Seric return (getgid()); 1924326Seric } 1934326Seric 19433936Sbostic /* 1959369Seric ** USERNAME -- return the user id of the logged in user. 1969369Seric ** 1979369Seric ** Parameters: 1989369Seric ** none. 1999369Seric ** 2009369Seric ** Returns: 2019369Seric ** The login name of the logged in user. 2029369Seric ** 2039369Seric ** Side Effects: 2049369Seric ** none. 2059369Seric ** 2069369Seric ** Notes: 2079369Seric ** The return value is statically allocated. 2089369Seric */ 2099369Seric 2109369Seric char * 2119369Seric username() 2129369Seric { 21317469Seric static char *myname = NULL; 2149369Seric extern char *getlogin(); 21519904Smiriam register struct passwd *pw; 2169369Seric 21717469Seric /* cache the result */ 21817469Seric if (myname == NULL) 21917469Seric { 22017469Seric myname = getlogin(); 22117469Seric if (myname == NULL || myname[0] == '\0') 22217469Seric { 22317469Seric 22417469Seric pw = getpwuid(getruid()); 22517469Seric if (pw != NULL) 22640993Sbostic myname = newstr(pw->pw_name); 22717469Seric } 22819904Smiriam else 22919904Smiriam { 23019873Smiriam 23140993Sbostic myname = newstr(myname); 23240993Sbostic if ((pw = getpwnam(myname)) == NULL || 23340993Sbostic getuid() != pw->pw_uid) 23419904Smiriam { 23519873Smiriam pw = getpwuid(getuid()); 23624945Seric if (pw != NULL) 23740993Sbostic myname = newstr(pw->pw_name); 23819873Smiriam } 23919873Smiriam } 24017469Seric if (myname == NULL || myname[0] == '\0') 24117469Seric { 24217469Seric syserr("Who are you?"); 24317469Seric myname = "postmaster"; 24417469Seric } 24517469Seric } 24617469Seric 24717469Seric return (myname); 2489369Seric } 2499369Seric /* 2504190Seric ** TTYPATH -- Get the path of the user's tty 251294Seric ** 252294Seric ** Returns the pathname of the user's tty. Returns NULL if 253294Seric ** the user is not logged in or if s/he has write permission 254294Seric ** denied. 255294Seric ** 256294Seric ** Parameters: 257294Seric ** none 258294Seric ** 259294Seric ** Returns: 260294Seric ** pathname of the user's tty. 261294Seric ** NULL if not logged in or write permission denied. 262294Seric ** 263294Seric ** Side Effects: 264294Seric ** none. 265294Seric ** 266294Seric ** WARNING: 267294Seric ** Return value is in a local buffer. 268294Seric ** 269294Seric ** Called By: 270294Seric ** savemail 271294Seric */ 272294Seric 273294Seric # include <sys/stat.h> 274294Seric 275294Seric char * 276294Seric ttypath() 277294Seric { 278294Seric struct stat stbuf; 279294Seric register char *pathn; 280294Seric extern char *ttyname(); 2814081Seric extern char *getlogin(); 282294Seric 283294Seric /* compute the pathname of the controlling tty */ 2849369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 2859369Seric (pathn = ttyname(0)) == NULL) 286294Seric { 287294Seric errno = 0; 288294Seric return (NULL); 289294Seric } 290294Seric 291294Seric /* see if we have write permission */ 2922967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 293294Seric { 294294Seric errno = 0; 295294Seric return (NULL); 296294Seric } 297294Seric 298294Seric /* see if the user is logged in */ 299294Seric if (getlogin() == NULL) 300294Seric return (NULL); 301294Seric 302294Seric /* looks good */ 303294Seric return (pathn); 304294Seric } 3052967Seric /* 3062967Seric ** CHECKCOMPAT -- check for From and To person compatible. 3072967Seric ** 3082967Seric ** This routine can be supplied on a per-installation basis 3092967Seric ** to determine whether a person is allowed to send a message. 3102967Seric ** This allows restriction of certain types of internet 3112967Seric ** forwarding or registration of users. 3122967Seric ** 3132967Seric ** If the hosts are found to be incompatible, an error 3142967Seric ** message should be given using "usrerr" and FALSE should 3152967Seric ** be returned. 3162967Seric ** 3174288Seric ** 'NoReturn' can be set to suppress the return-to-sender 3184288Seric ** function; this should be done on huge messages. 3194288Seric ** 3202967Seric ** Parameters: 3212967Seric ** to -- the person being sent to. 3222967Seric ** 3232967Seric ** Returns: 3242967Seric ** TRUE -- ok to send. 3252967Seric ** FALSE -- not ok. 3262967Seric ** 3272967Seric ** Side Effects: 3282967Seric ** none (unless you include the usrerr stuff) 3292967Seric */ 3302967Seric 3312967Seric bool 3322967Seric checkcompat(to) 3332967Seric register ADDRESS *to; 3342967Seric { 33512133Seric # ifdef lint 33612133Seric if (to == NULL) 33712133Seric to++; 33812133Seric # endif lint 33910698Seric # ifdef EXAMPLE_CODE 34010698Seric /* this code is intended as an example only */ 3414437Seric register STAB *s; 3424437Seric 3434437Seric s = stab("arpa", ST_MAILER, ST_FIND); 3449369Seric if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 3459369Seric to->q_mailer == s->s_mailer) 3464437Seric { 3474437Seric usrerr("No ARPA mail through this machine: see your system administration"); 34810698Seric /* NoReturn = TRUE; to supress return copy */ 3494437Seric return (FALSE); 3504437Seric } 35110698Seric # endif EXAMPLE_CODE 3522967Seric return (TRUE); 3532967Seric } 3549369Seric /* 3559369Seric ** HOLDSIGS -- arrange to hold all signals 3569369Seric ** 3579369Seric ** Parameters: 3589369Seric ** none. 3599369Seric ** 3609369Seric ** Returns: 3619369Seric ** none. 3629369Seric ** 3639369Seric ** Side Effects: 3649369Seric ** Arranges that signals are held. 3659369Seric */ 3669369Seric 3679369Seric holdsigs() 3689369Seric { 3699369Seric } 3709369Seric /* 3719369Seric ** RLSESIGS -- arrange to release all signals 3729369Seric ** 3739369Seric ** This undoes the effect of holdsigs. 3749369Seric ** 3759369Seric ** Parameters: 3769369Seric ** none. 3779369Seric ** 3789369Seric ** Returns: 3799369Seric ** none. 3809369Seric ** 3819369Seric ** Side Effects: 3829369Seric ** Arranges that signals are released. 3839369Seric */ 3849369Seric 3859369Seric rlsesigs() 3869369Seric { 3879369Seric } 38814872Seric /* 38914872Seric ** GETLA -- get the current load average 39014872Seric ** 39114881Seric ** This code stolen from la.c. 39214881Seric ** 39314872Seric ** Parameters: 39414872Seric ** none. 39514872Seric ** 39614872Seric ** Returns: 39714872Seric ** The current load average as an integer. 39814872Seric ** 39914872Seric ** Side Effects: 40014872Seric ** none. 40114872Seric */ 40214872Seric 40351920Seric /* try to guess what style of load average we have */ 40451920Seric #define LA_ZERO 1 /* always return load average as zero */ 40551920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 40651920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 40751920Seric #define LA_SUBR 4 /* call getloadavg */ 40814872Seric 40951920Seric #ifndef LA_TYPE 41051920Seric # if defined(sun) 41151920Seric # define LA_TYPE LA_INT 41251920Seric # endif 41351920Seric # if defined(mips) 41451920Seric /* Ultrix or RISC/os */ 41551920Seric # define LA_TYPE LA_INT 41651920Seric # define LA_AVENRUN "avenrun" 41751920Seric # endif 41851920Seric # if defined(hpux) 41951920Seric # define LA_TYPE LA_FLOAT 42051920Seric # endif 42151920Seric # if defined(BSD) 42251920Seric # define LA_TYPE LA_SUBR 42351920Seric # endif 42451920Seric 42551920Seric # ifndef LA_TYPE 42651920Seric # define LA_TYPE LA_ZERO 42751920Seric # endif 42851920Seric #endif 42951920Seric 43051920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 43151920Seric 43214872Seric #include <nlist.h> 43351920Seric #include <fcntl.h> 43414872Seric 43551920Seric #ifndef LA_AVENRUN 43651920Seric #define LA_AVENRUN "_avenrun" 43751920Seric #endif 43851920Seric 43951920Seric /* _PATH_UNIX should be defined in <paths.h> */ 44051920Seric #ifndef _PATH_UNIX 44151920Seric # if defined(hpux) 44251920Seric # define _PATH_UNIX "/hp-ux" 44351920Seric # endif 44451920Seric # if defined(mips) && !defined(ultrix) 44551920Seric /* powerful RISC/os */ 44651920Seric # define _PATH_UNIX "/unix" 44751920Seric # endif 44851920Seric # ifndef _PATH_UNIX 44951920Seric # define _PATH_UNIX "/vmunix" 45051920Seric # endif 45151920Seric #endif 45251920Seric 45314872Seric struct nlist Nl[] = 45414872Seric { 45551920Seric { LA_AVENRUN }, 45614872Seric #define X_AVENRUN 0 45714872Seric { 0 }, 45814872Seric }; 45914872Seric 46051920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 46151920Seric # define FSHIFT 8 46251920Seric # define FSCALE (1 << FSHIFT) 46351920Seric #endif 46440930Srick 46514872Seric getla() 46614872Seric { 46714872Seric static int kmem = -1; 46851920Seric #if LA_TYPE == LA_INT 46924943Seric long avenrun[3]; 47051920Seric #else 47151920Seric double avenrun[3]; 47251920Seric #endif 47325615Seric extern off_t lseek(); 47414872Seric 47514872Seric if (kmem < 0) 47614872Seric { 47724945Seric kmem = open("/dev/kmem", 0, 0); 47814872Seric if (kmem < 0) 47914872Seric return (-1); 48051920Seric (void) fcntl(kmem, F_SETFD, 1); 48151920Seric nlist(_PATH_UNIX, Nl); 48214872Seric if (Nl[0].n_type == 0) 48314872Seric return (-1); 48414872Seric } 48524945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 48623118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 48719967Seric { 48819967Seric /* thank you Ian */ 48919967Seric return (-1); 49019967Seric } 49151920Seric #if LA_TYPE == LA_INT 49224943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 49351920Seric #else 49451920Seric return ((int) (avenrun[0] + 0.5)); 49551920Seric #endif 49614872Seric } 49714872Seric 49851773Seric #else 49951920Seric #if LA_TYPE == LA_SUBR 50051773Seric 50151773Seric getla() 50251773Seric { 50351920Seric double avenrun[3]; 50451920Seric 50551920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 50651920Seric return (-1); 50751920Seric return ((int) (avenrun[0] + 0.5)); 50851773Seric } 50951773Seric 51051773Seric #else 51151773Seric 51251773Seric getla() 51351773Seric { 51451920Seric return (0); 51551773Seric } 51651773Seric 51751773Seric #endif 51851773Seric #endif 51924943Seric /* 52024943Seric ** SHOULDQUEUE -- should this message be queued or sent? 52124943Seric ** 52224943Seric ** Compares the message cost to the load average to decide. 52324943Seric ** 52424943Seric ** Parameters: 52524943Seric ** pri -- the priority of the message in question. 52624943Seric ** 52724943Seric ** Returns: 52824943Seric ** TRUE -- if this message should be queued up for the 52924943Seric ** time being. 53024943Seric ** FALSE -- if the load is low enough to send this message. 53124943Seric ** 53224943Seric ** Side Effects: 53324943Seric ** none. 53424943Seric */ 53524943Seric 53624943Seric bool 53724943Seric shouldqueue(pri) 53824943Seric long pri; 53924943Seric { 54051920Seric if (CurrentLA < QueueLA) 54124943Seric return (FALSE); 54251920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 54324943Seric } 54424943Seric /* 545*53037Seric ** REFUSECONNECTIONS -- decide if connections should be refused 546*53037Seric ** 547*53037Seric ** Parameters: 548*53037Seric ** none. 549*53037Seric ** 550*53037Seric ** Returns: 551*53037Seric ** TRUE if incoming SMTP connections should be refused 552*53037Seric ** (for now). 553*53037Seric ** FALSE if we should accept new work. 554*53037Seric ** 555*53037Seric ** Side Effects: 556*53037Seric ** none. 557*53037Seric */ 558*53037Seric 559*53037Seric bool 560*53037Seric refuseconnections() 561*53037Seric { 562*53037Seric /* this is probably too simplistic */ 563*53037Seric return (CurrentLA > RefuseLA); 564*53037Seric } 565*53037Seric /* 56624943Seric ** SETPROCTITLE -- set process title for ps 56724943Seric ** 56824943Seric ** Parameters: 56924943Seric ** fmt -- a printf style format string. 57024943Seric ** a, b, c -- possible parameters to fmt. 57124943Seric ** 57224943Seric ** Returns: 57324943Seric ** none. 57424943Seric ** 57524943Seric ** Side Effects: 57624943Seric ** Clobbers argv of our main procedure so ps(1) will 57724943Seric ** display the title. 57824943Seric */ 57924943Seric 58024943Seric /*VARARGS1*/ 58124943Seric setproctitle(fmt, a, b, c) 58224943Seric char *fmt; 58324943Seric { 58424943Seric # ifdef SETPROCTITLE 58524943Seric register char *p; 58625049Seric register int i; 58724943Seric extern char **Argv; 58824943Seric extern char *LastArgv; 58925049Seric char buf[MAXLINE]; 59024943Seric 59125049Seric (void) sprintf(buf, fmt, a, b, c); 59224943Seric 59324943Seric /* make ps print "(sendmail)" */ 59425049Seric p = Argv[0]; 59524943Seric *p++ = '-'; 59624943Seric 59725049Seric i = strlen(buf); 59825049Seric if (i > LastArgv - p - 2) 59925049Seric { 60025049Seric i = LastArgv - p - 2; 60125049Seric buf[i] = '\0'; 60225049Seric } 60325049Seric (void) strcpy(p, buf); 60425049Seric p += i; 60524943Seric while (p < LastArgv) 60624943Seric *p++ = ' '; 60724943Seric # endif SETPROCTITLE 60824943Seric } 60925698Seric /* 61025698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 61125698Seric ** 61225698Seric ** Parameters: 61325698Seric ** none. 61425698Seric ** 61525698Seric ** Returns: 61625698Seric ** none. 61725698Seric ** 61825698Seric ** Side Effects: 61925698Seric ** Picks up extant zombies. 62025698Seric */ 62125698Seric 62225698Seric # include <sys/wait.h> 62325698Seric 62446928Sbostic void 62525698Seric reapchild() 62625698Seric { 62725698Seric # ifdef WNOHANG 62825698Seric union wait status; 62925698Seric 63046928Sbostic while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 63125698Seric continue; 63225698Seric # else WNOHANG 63325698Seric auto int status; 63425698Seric 63546928Sbostic while (wait((int *)&status) > 0) 63625698Seric continue; 63725698Seric # endif WNOHANG 63825698Seric } 639