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*52106Seric static char sccsid[] = "@(#)conf.c 5.33 (Berkeley) 01/04/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 ** Compilation Flags: 2514872Seric ** VMUNIX -- running on a Berkeley UNIX system. 26294Seric ** 271388Seric ** Configuration Variables: 282897Seric ** HdrInfo -- a table describing well-known header fields. 292897Seric ** Each entry has the field name and some flags, 304147Seric ** which are described in sendmail.h. 314093Seric ** 324093Seric ** Notes: 334093Seric ** I have tried to put almost all the reasonable 344093Seric ** configuration information into the configuration 354093Seric ** file read at runtime. My intent is that anything 364093Seric ** here is a function of the version of UNIX you 374093Seric ** are running, or is really static -- for example 384093Seric ** the headers are a superset of widely used 394093Seric ** protocols. If you find yourself playing with 404093Seric ** this file too much, you may be making a mistake! 41294Seric */ 42294Seric 43294Seric 44294Seric 45294Seric 464437Seric /* 472897Seric ** Header info table 483057Seric ** Final (null) entry contains the flags used for any other field. 494147Seric ** 504147Seric ** Not all of these are actually handled specially by sendmail 514147Seric ** at this time. They are included as placeholders, to let 524147Seric ** you know that "someday" I intend to have sendmail do 534147Seric ** something with them. 542897Seric */ 552897Seric 562897Seric struct hdrinfo HdrInfo[] = 572897Seric { 588060Seric /* originator fields, most to least significant */ 5911417Seric "resent-sender", H_FROM|H_RESENT, 6011417Seric "resent-from", H_FROM|H_RESENT, 6125686Seric "resent-reply-to", H_FROM|H_RESENT, 629055Seric "sender", H_FROM, 639055Seric "from", H_FROM, 6425686Seric "reply-to", H_FROM, 659055Seric "full-name", H_ACHECK, 669055Seric "return-receipt-to", H_FROM, 679055Seric "errors-to", H_FROM, 688060Seric /* destination fields */ 699055Seric "to", H_RCPT, 7011417Seric "resent-to", H_RCPT|H_RESENT, 719055Seric "cc", H_RCPT, 7211417Seric "resent-cc", H_RCPT|H_RESENT, 739055Seric "bcc", H_RCPT|H_ACHECK, 7411417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 758060Seric /* message identification and control */ 7611417Seric "message-id", 0, 7711417Seric "resent-message-id", H_RESENT, 789055Seric "message", H_EOH, 799055Seric "text", H_EOH, 8011417Seric /* date fields */ 8111417Seric "date", 0, 8211417Seric "resent-date", H_RESENT, 838060Seric /* trace fields */ 849055Seric "received", H_TRACE|H_FORCE, 859055Seric "via", H_TRACE|H_FORCE, 869055Seric "mail-from", H_TRACE|H_FORCE, 878060Seric 889055Seric NULL, 0, 892897Seric }; 904166Seric 914166Seric 924166Seric /* 934166Seric ** ARPANET error message numbers. 944166Seric */ 954166Seric 967956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 977956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 987956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 997956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 1004282Seric 1014282Seric 1024282Seric 1034282Seric /* 1044282Seric ** Location of system files/databases/etc. 1054282Seric */ 1064282Seric 10740980Sbostic char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 10840980Sbostic char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 1099039Seric 1109064Seric 1119064Seric 1129039Seric /* 11324943Seric ** Miscellaneous stuff. 1149039Seric */ 1159039Seric 11624943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 11724943Seric /* 11824943Seric ** SETDEFAULTS -- set default values 11924943Seric ** 12024943Seric ** Because of the way freezing is done, these must be initialized 12124943Seric ** using direct code. 12224943Seric ** 12324943Seric ** Parameters: 12424943Seric ** none. 12524943Seric ** 12624943Seric ** Returns: 12724943Seric ** none. 12824943Seric ** 12924943Seric ** Side Effects: 13024943Seric ** Initializes a bunch of global variables to their 13124943Seric ** default values. 13224943Seric */ 13324943Seric 13424943Seric setdefaults() 13524943Seric { 13624943Seric QueueLA = 8; 13724943Seric QueueFactor = 10000; 13824943Seric RefuseLA = 12; 13924943Seric SpaceSub = ' '; 14024981Seric WkRecipFact = 1000; 14124981Seric WkClassFact = 1800; 14225812Seric WkTimeFact = 9000; 14324981Seric FileMode = 0644; 14424981Seric DefUid = 1; 14524981Seric DefGid = 1; 14647284Seric CheckpointInterval = 10; 14751305Seric MaxHopCount = MAXHOP; 14852105Seric SendMode = SM_FORK; 14952105Seric ErrorMode = EM_PRINT; 150*52106Seric EightBit = FALSE; 15140973Sbostic setdefuser(); 15224943Seric } 153294Seric 15440973Sbostic 1554326Seric /* 15640973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 15740973Sbostic */ 15840973Sbostic 15940973Sbostic setdefuser() 16040973Sbostic { 16140973Sbostic struct passwd *defpwent; 16240973Sbostic 16340973Sbostic if (DefUser != NULL) 16440973Sbostic free(DefUser); 16540973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 16640973Sbostic DefUser = newstr(defpwent->pw_name); 16740973Sbostic else 16840973Sbostic DefUser = newstr("nobody"); 16940973Sbostic } 17040973Sbostic 17140973Sbostic 17240973Sbostic /* 1734326Seric ** GETRUID -- get real user id (V7) 1744326Seric */ 1754326Seric 1764326Seric getruid() 1774326Seric { 1789274Seric if (OpMode == MD_DAEMON) 1794536Seric return (RealUid); 1804536Seric else 1814536Seric return (getuid()); 1824326Seric } 1834326Seric 1844326Seric 1854326Seric /* 1864326Seric ** GETRGID -- get real group id (V7). 1874326Seric */ 1884326Seric 1894326Seric getrgid() 1904326Seric { 1919274Seric if (OpMode == MD_DAEMON) 1924536Seric return (RealGid); 1934536Seric else 1944536Seric return (getgid()); 1954326Seric } 1964326Seric 19733936Sbostic /* 1989369Seric ** USERNAME -- return the user id of the logged in user. 1999369Seric ** 2009369Seric ** Parameters: 2019369Seric ** none. 2029369Seric ** 2039369Seric ** Returns: 2049369Seric ** The login name of the logged in user. 2059369Seric ** 2069369Seric ** Side Effects: 2079369Seric ** none. 2089369Seric ** 2099369Seric ** Notes: 2109369Seric ** The return value is statically allocated. 2119369Seric */ 2129369Seric 2139369Seric char * 2149369Seric username() 2159369Seric { 21617469Seric static char *myname = NULL; 2179369Seric extern char *getlogin(); 21819904Smiriam register struct passwd *pw; 2199369Seric 22017469Seric /* cache the result */ 22117469Seric if (myname == NULL) 22217469Seric { 22317469Seric myname = getlogin(); 22417469Seric if (myname == NULL || myname[0] == '\0') 22517469Seric { 22617469Seric 22717469Seric pw = getpwuid(getruid()); 22817469Seric if (pw != NULL) 22940993Sbostic myname = newstr(pw->pw_name); 23017469Seric } 23119904Smiriam else 23219904Smiriam { 23319873Smiriam 23440993Sbostic myname = newstr(myname); 23540993Sbostic if ((pw = getpwnam(myname)) == NULL || 23640993Sbostic getuid() != pw->pw_uid) 23719904Smiriam { 23819873Smiriam pw = getpwuid(getuid()); 23924945Seric if (pw != NULL) 24040993Sbostic myname = newstr(pw->pw_name); 24119873Smiriam } 24219873Smiriam } 24317469Seric if (myname == NULL || myname[0] == '\0') 24417469Seric { 24517469Seric syserr("Who are you?"); 24617469Seric myname = "postmaster"; 24717469Seric } 24817469Seric } 24917469Seric 25017469Seric return (myname); 2519369Seric } 2529369Seric /* 2534190Seric ** TTYPATH -- Get the path of the user's tty 254294Seric ** 255294Seric ** Returns the pathname of the user's tty. Returns NULL if 256294Seric ** the user is not logged in or if s/he has write permission 257294Seric ** denied. 258294Seric ** 259294Seric ** Parameters: 260294Seric ** none 261294Seric ** 262294Seric ** Returns: 263294Seric ** pathname of the user's tty. 264294Seric ** NULL if not logged in or write permission denied. 265294Seric ** 266294Seric ** Side Effects: 267294Seric ** none. 268294Seric ** 269294Seric ** WARNING: 270294Seric ** Return value is in a local buffer. 271294Seric ** 272294Seric ** Called By: 273294Seric ** savemail 274294Seric */ 275294Seric 276294Seric # include <sys/stat.h> 277294Seric 278294Seric char * 279294Seric ttypath() 280294Seric { 281294Seric struct stat stbuf; 282294Seric register char *pathn; 283294Seric extern char *ttyname(); 2844081Seric extern char *getlogin(); 285294Seric 286294Seric /* compute the pathname of the controlling tty */ 2879369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 2889369Seric (pathn = ttyname(0)) == NULL) 289294Seric { 290294Seric errno = 0; 291294Seric return (NULL); 292294Seric } 293294Seric 294294Seric /* see if we have write permission */ 2952967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 296294Seric { 297294Seric errno = 0; 298294Seric return (NULL); 299294Seric } 300294Seric 301294Seric /* see if the user is logged in */ 302294Seric if (getlogin() == NULL) 303294Seric return (NULL); 304294Seric 305294Seric /* looks good */ 306294Seric return (pathn); 307294Seric } 3082967Seric /* 3092967Seric ** CHECKCOMPAT -- check for From and To person compatible. 3102967Seric ** 3112967Seric ** This routine can be supplied on a per-installation basis 3122967Seric ** to determine whether a person is allowed to send a message. 3132967Seric ** This allows restriction of certain types of internet 3142967Seric ** forwarding or registration of users. 3152967Seric ** 3162967Seric ** If the hosts are found to be incompatible, an error 3172967Seric ** message should be given using "usrerr" and FALSE should 3182967Seric ** be returned. 3192967Seric ** 3204288Seric ** 'NoReturn' can be set to suppress the return-to-sender 3214288Seric ** function; this should be done on huge messages. 3224288Seric ** 3232967Seric ** Parameters: 3242967Seric ** to -- the person being sent to. 3252967Seric ** 3262967Seric ** Returns: 3272967Seric ** TRUE -- ok to send. 3282967Seric ** FALSE -- not ok. 3292967Seric ** 3302967Seric ** Side Effects: 3312967Seric ** none (unless you include the usrerr stuff) 3322967Seric */ 3332967Seric 3342967Seric bool 3352967Seric checkcompat(to) 3362967Seric register ADDRESS *to; 3372967Seric { 33812133Seric # ifdef lint 33912133Seric if (to == NULL) 34012133Seric to++; 34112133Seric # endif lint 34210698Seric # ifdef EXAMPLE_CODE 34310698Seric /* this code is intended as an example only */ 3444437Seric register STAB *s; 3454437Seric 3464437Seric s = stab("arpa", ST_MAILER, ST_FIND); 3479369Seric if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 3489369Seric to->q_mailer == s->s_mailer) 3494437Seric { 3504437Seric usrerr("No ARPA mail through this machine: see your system administration"); 35110698Seric /* NoReturn = TRUE; to supress return copy */ 3524437Seric return (FALSE); 3534437Seric } 35410698Seric # endif EXAMPLE_CODE 3552967Seric return (TRUE); 3562967Seric } 3579369Seric /* 3589369Seric ** HOLDSIGS -- arrange to hold all signals 3599369Seric ** 3609369Seric ** Parameters: 3619369Seric ** none. 3629369Seric ** 3639369Seric ** Returns: 3649369Seric ** none. 3659369Seric ** 3669369Seric ** Side Effects: 3679369Seric ** Arranges that signals are held. 3689369Seric */ 3699369Seric 3709369Seric holdsigs() 3719369Seric { 3729369Seric } 3739369Seric /* 3749369Seric ** RLSESIGS -- arrange to release all signals 3759369Seric ** 3769369Seric ** This undoes the effect of holdsigs. 3779369Seric ** 3789369Seric ** Parameters: 3799369Seric ** none. 3809369Seric ** 3819369Seric ** Returns: 3829369Seric ** none. 3839369Seric ** 3849369Seric ** Side Effects: 3859369Seric ** Arranges that signals are released. 3869369Seric */ 3879369Seric 3889369Seric rlsesigs() 3899369Seric { 3909369Seric } 39114872Seric /* 39214872Seric ** GETLA -- get the current load average 39314872Seric ** 39414881Seric ** This code stolen from la.c. 39514881Seric ** 39614872Seric ** Parameters: 39714872Seric ** none. 39814872Seric ** 39914872Seric ** Returns: 40014872Seric ** The current load average as an integer. 40114872Seric ** 40214872Seric ** Side Effects: 40314872Seric ** none. 40414872Seric */ 40514872Seric 40651920Seric /* try to guess what style of load average we have */ 40751920Seric #define LA_ZERO 1 /* always return load average as zero */ 40851920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 40951920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 41051920Seric #define LA_SUBR 4 /* call getloadavg */ 41114872Seric 41251920Seric #ifndef LA_TYPE 41351920Seric # if defined(sun) 41451920Seric # define LA_TYPE LA_INT 41551920Seric # endif 41651920Seric # if defined(mips) 41751920Seric /* Ultrix or RISC/os */ 41851920Seric # define LA_TYPE LA_INT 41951920Seric # define LA_AVENRUN "avenrun" 42051920Seric # endif 42151920Seric # if defined(hpux) 42251920Seric # define LA_TYPE LA_FLOAT 42351920Seric # endif 42451920Seric # if defined(BSD) 42551920Seric # define LA_TYPE LA_SUBR 42651920Seric # endif 42751920Seric 42851920Seric # ifndef LA_TYPE 42951920Seric # define LA_TYPE LA_ZERO 43051920Seric # endif 43151920Seric #endif 43251920Seric 43351920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 43451920Seric 43514872Seric #include <nlist.h> 43651920Seric #include <fcntl.h> 43714872Seric 43851920Seric #ifndef LA_AVENRUN 43951920Seric #define LA_AVENRUN "_avenrun" 44051920Seric #endif 44151920Seric 44251920Seric /* _PATH_UNIX should be defined in <paths.h> */ 44351920Seric #ifndef _PATH_UNIX 44451920Seric # if defined(hpux) 44551920Seric # define _PATH_UNIX "/hp-ux" 44651920Seric # endif 44751920Seric # if defined(mips) && !defined(ultrix) 44851920Seric /* powerful RISC/os */ 44951920Seric # define _PATH_UNIX "/unix" 45051920Seric # endif 45151920Seric # ifndef _PATH_UNIX 45251920Seric # define _PATH_UNIX "/vmunix" 45351920Seric # endif 45451920Seric #endif 45551920Seric 45614872Seric struct nlist Nl[] = 45714872Seric { 45851920Seric { LA_AVENRUN }, 45914872Seric #define X_AVENRUN 0 46014872Seric { 0 }, 46114872Seric }; 46214872Seric 46351920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 46451920Seric # define FSHIFT 8 46551920Seric # define FSCALE (1 << FSHIFT) 46651920Seric #endif 46740930Srick 46814872Seric getla() 46914872Seric { 47014872Seric static int kmem = -1; 47151920Seric #if LA_TYPE == LA_INT 47224943Seric long avenrun[3]; 47351920Seric #else 47451920Seric double avenrun[3]; 47551920Seric #endif 47625615Seric extern off_t lseek(); 47714872Seric 47814872Seric if (kmem < 0) 47914872Seric { 48024945Seric kmem = open("/dev/kmem", 0, 0); 48114872Seric if (kmem < 0) 48214872Seric return (-1); 48351920Seric (void) fcntl(kmem, F_SETFD, 1); 48451920Seric nlist(_PATH_UNIX, Nl); 48514872Seric if (Nl[0].n_type == 0) 48614872Seric return (-1); 48714872Seric } 48824945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 48923118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 49019967Seric { 49119967Seric /* thank you Ian */ 49219967Seric return (-1); 49319967Seric } 49451920Seric #if LA_TYPE == LA_INT 49524943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 49651920Seric #else 49751920Seric return ((int) (avenrun[0] + 0.5)); 49851920Seric #endif 49914872Seric } 50014872Seric 50151773Seric #else 50251920Seric #if LA_TYPE == LA_SUBR 50351773Seric 50451773Seric getla() 50551773Seric { 50651920Seric double avenrun[3]; 50751920Seric 50851920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 50951920Seric return (-1); 51051920Seric return ((int) (avenrun[0] + 0.5)); 51151773Seric } 51251773Seric 51351773Seric #else 51451773Seric 51551773Seric getla() 51651773Seric { 51751920Seric return (0); 51851773Seric } 51951773Seric 52051773Seric #endif 52151773Seric #endif 52224943Seric /* 52324943Seric ** SHOULDQUEUE -- should this message be queued or sent? 52424943Seric ** 52524943Seric ** Compares the message cost to the load average to decide. 52624943Seric ** 52724943Seric ** Parameters: 52824943Seric ** pri -- the priority of the message in question. 52924943Seric ** 53024943Seric ** Returns: 53124943Seric ** TRUE -- if this message should be queued up for the 53224943Seric ** time being. 53324943Seric ** FALSE -- if the load is low enough to send this message. 53424943Seric ** 53524943Seric ** Side Effects: 53624943Seric ** none. 53724943Seric */ 53824943Seric 53924943Seric bool 54024943Seric shouldqueue(pri) 54124943Seric long pri; 54224943Seric { 54351920Seric if (CurrentLA < QueueLA) 54424943Seric return (FALSE); 54551920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 54624943Seric } 54724943Seric /* 54824943Seric ** SETPROCTITLE -- set process title for ps 54924943Seric ** 55024943Seric ** Parameters: 55124943Seric ** fmt -- a printf style format string. 55224943Seric ** a, b, c -- possible parameters to fmt. 55324943Seric ** 55424943Seric ** Returns: 55524943Seric ** none. 55624943Seric ** 55724943Seric ** Side Effects: 55824943Seric ** Clobbers argv of our main procedure so ps(1) will 55924943Seric ** display the title. 56024943Seric */ 56124943Seric 56224943Seric /*VARARGS1*/ 56324943Seric setproctitle(fmt, a, b, c) 56424943Seric char *fmt; 56524943Seric { 56624943Seric # ifdef SETPROCTITLE 56724943Seric register char *p; 56825049Seric register int i; 56924943Seric extern char **Argv; 57024943Seric extern char *LastArgv; 57125049Seric char buf[MAXLINE]; 57224943Seric 57325049Seric (void) sprintf(buf, fmt, a, b, c); 57424943Seric 57524943Seric /* make ps print "(sendmail)" */ 57625049Seric p = Argv[0]; 57724943Seric *p++ = '-'; 57824943Seric 57925049Seric i = strlen(buf); 58025049Seric if (i > LastArgv - p - 2) 58125049Seric { 58225049Seric i = LastArgv - p - 2; 58325049Seric buf[i] = '\0'; 58425049Seric } 58525049Seric (void) strcpy(p, buf); 58625049Seric p += i; 58724943Seric while (p < LastArgv) 58824943Seric *p++ = ' '; 58924943Seric # endif SETPROCTITLE 59024943Seric } 59125698Seric /* 59225698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 59325698Seric ** 59425698Seric ** Parameters: 59525698Seric ** none. 59625698Seric ** 59725698Seric ** Returns: 59825698Seric ** none. 59925698Seric ** 60025698Seric ** Side Effects: 60125698Seric ** Picks up extant zombies. 60225698Seric */ 60325698Seric 60425698Seric # ifdef VMUNIX 60525698Seric # include <sys/wait.h> 60625698Seric # endif VMUNIX 60725698Seric 60846928Sbostic void 60925698Seric reapchild() 61025698Seric { 61125698Seric # ifdef WNOHANG 61225698Seric union wait status; 61325698Seric 61446928Sbostic while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 61525698Seric continue; 61625698Seric # else WNOHANG 61725698Seric auto int status; 61825698Seric 61946928Sbostic while (wait((int *)&status) > 0) 62025698Seric continue; 62125698Seric # endif WNOHANG 62225698Seric } 623