122698Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 633728Sbostic * Redistribution and use in source and binary forms are permitted 734920Sbostic * provided that the above copyright notice and this paragraph are 834920Sbostic * duplicated in all such forms and that any documentation, 934920Sbostic * advertising materials, and other materials related to such 1034920Sbostic * distribution and use acknowledge that the software was developed 1134920Sbostic * by the University of California, Berkeley. The name of the 1234920Sbostic * University may not be used to endorse or promote products derived 1334920Sbostic * from this software without specific prior written permission. 1434920Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1534920Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1634920Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1733728Sbostic */ 1822698Sdist 1922698Sdist #ifndef lint 20*40993Sbostic static char sccsid[] = "@(#)conf.c 5.25 (Berkeley) 04/19/90"; 2133728Sbostic #endif /* not lint */ 2222698Sdist 2314881Seric # include <sys/ioctl.h> 2424943Seric # include <sys/param.h> 2536928Sbostic # include <pwd.h> 263309Seric # include "sendmail.h" 2740980Sbostic # include "pathnames.h" 28404Seric 29294Seric /* 303309Seric ** CONF.C -- Sendmail Configuration Tables. 31294Seric ** 32294Seric ** Defines the configuration of this installation. 33294Seric ** 341388Seric ** Compilation Flags: 3514872Seric ** VMUNIX -- running on a Berkeley UNIX system. 36294Seric ** 371388Seric ** Configuration Variables: 382897Seric ** HdrInfo -- a table describing well-known header fields. 392897Seric ** Each entry has the field name and some flags, 404147Seric ** which are described in sendmail.h. 414093Seric ** 424093Seric ** Notes: 434093Seric ** I have tried to put almost all the reasonable 444093Seric ** configuration information into the configuration 454093Seric ** file read at runtime. My intent is that anything 464093Seric ** here is a function of the version of UNIX you 474093Seric ** are running, or is really static -- for example 484093Seric ** the headers are a superset of widely used 494093Seric ** protocols. If you find yourself playing with 504093Seric ** this file too much, you may be making a mistake! 51294Seric */ 52294Seric 53294Seric 54294Seric 55294Seric 564437Seric /* 572897Seric ** Header info table 583057Seric ** Final (null) entry contains the flags used for any other field. 594147Seric ** 604147Seric ** Not all of these are actually handled specially by sendmail 614147Seric ** at this time. They are included as placeholders, to let 624147Seric ** you know that "someday" I intend to have sendmail do 634147Seric ** something with them. 642897Seric */ 652897Seric 662897Seric struct hdrinfo HdrInfo[] = 672897Seric { 688060Seric /* originator fields, most to least significant */ 6911417Seric "resent-sender", H_FROM|H_RESENT, 7011417Seric "resent-from", H_FROM|H_RESENT, 7125686Seric "resent-reply-to", H_FROM|H_RESENT, 729055Seric "sender", H_FROM, 739055Seric "from", H_FROM, 7425686Seric "reply-to", H_FROM, 759055Seric "full-name", H_ACHECK, 769055Seric "return-receipt-to", H_FROM, 779055Seric "errors-to", H_FROM, 788060Seric /* destination fields */ 799055Seric "to", H_RCPT, 8011417Seric "resent-to", H_RCPT|H_RESENT, 819055Seric "cc", H_RCPT, 8211417Seric "resent-cc", H_RCPT|H_RESENT, 839055Seric "bcc", H_RCPT|H_ACHECK, 8411417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 858060Seric /* message identification and control */ 8611417Seric "message-id", 0, 8711417Seric "resent-message-id", H_RESENT, 889055Seric "message", H_EOH, 899055Seric "text", H_EOH, 9011417Seric /* date fields */ 9111417Seric "date", 0, 9211417Seric "resent-date", H_RESENT, 938060Seric /* trace fields */ 949055Seric "received", H_TRACE|H_FORCE, 959055Seric "via", H_TRACE|H_FORCE, 969055Seric "mail-from", H_TRACE|H_FORCE, 978060Seric 989055Seric NULL, 0, 992897Seric }; 1004166Seric 1014166Seric 1024166Seric /* 1034166Seric ** ARPANET error message numbers. 1044166Seric */ 1054166Seric 1067956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 1077956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 1087956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 1097956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 1104282Seric 1114282Seric 1124282Seric 1134282Seric /* 1144282Seric ** Location of system files/databases/etc. 1154282Seric */ 1164282Seric 11740980Sbostic char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 11840980Sbostic char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 1199039Seric 1209064Seric 1219064Seric 1229039Seric /* 12324943Seric ** Miscellaneous stuff. 1249039Seric */ 1259039Seric 12624943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 12740938Srick extern int la; /* load average */ 12824943Seric /* 12924943Seric ** SETDEFAULTS -- set default values 13024943Seric ** 13124943Seric ** Because of the way freezing is done, these must be initialized 13224943Seric ** using direct code. 13324943Seric ** 13424943Seric ** Parameters: 13524943Seric ** none. 13624943Seric ** 13724943Seric ** Returns: 13824943Seric ** none. 13924943Seric ** 14024943Seric ** Side Effects: 14124943Seric ** Initializes a bunch of global variables to their 14224943Seric ** default values. 14324943Seric */ 14424943Seric 14524943Seric setdefaults() 14624943Seric { 14724943Seric QueueLA = 8; 14824943Seric QueueFactor = 10000; 14924943Seric RefuseLA = 12; 15024943Seric SpaceSub = ' '; 15124981Seric WkRecipFact = 1000; 15224981Seric WkClassFact = 1800; 15325812Seric WkTimeFact = 9000; 15424981Seric FileMode = 0644; 15524981Seric DefUid = 1; 15624981Seric DefGid = 1; 15740973Sbostic setdefuser(); 15824943Seric } 159294Seric 16040973Sbostic 1614326Seric /* 16240973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 16340973Sbostic */ 16440973Sbostic 16540973Sbostic setdefuser() 16640973Sbostic { 16740973Sbostic struct passwd *defpwent; 16840973Sbostic 16940973Sbostic if (DefUser != NULL) 17040973Sbostic free(DefUser); 17140973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 17240973Sbostic DefUser = newstr(defpwent->pw_name); 17340973Sbostic else 17440973Sbostic DefUser = newstr("nobody"); 17540973Sbostic } 17640973Sbostic 17740973Sbostic 17840973Sbostic /* 1794326Seric ** GETRUID -- get real user id (V7) 1804326Seric */ 1814326Seric 1824326Seric getruid() 1834326Seric { 1849274Seric if (OpMode == MD_DAEMON) 1854536Seric return (RealUid); 1864536Seric else 1874536Seric return (getuid()); 1884326Seric } 1894326Seric 1904326Seric 1914326Seric /* 1924326Seric ** GETRGID -- get real group id (V7). 1934326Seric */ 1944326Seric 1954326Seric getrgid() 1964326Seric { 1979274Seric if (OpMode == MD_DAEMON) 1984536Seric return (RealGid); 1994536Seric else 2004536Seric return (getgid()); 2014326Seric } 2024326Seric 20333936Sbostic /* 2049369Seric ** USERNAME -- return the user id of the logged in user. 2059369Seric ** 2069369Seric ** Parameters: 2079369Seric ** none. 2089369Seric ** 2099369Seric ** Returns: 2109369Seric ** The login name of the logged in user. 2119369Seric ** 2129369Seric ** Side Effects: 2139369Seric ** none. 2149369Seric ** 2159369Seric ** Notes: 2169369Seric ** The return value is statically allocated. 2179369Seric */ 2189369Seric 2199369Seric char * 2209369Seric username() 2219369Seric { 22217469Seric static char *myname = NULL; 2239369Seric extern char *getlogin(); 22419904Smiriam register struct passwd *pw; 22519904Smiriam extern struct passwd *getpwuid(); 2269369Seric 22717469Seric /* cache the result */ 22817469Seric if (myname == NULL) 22917469Seric { 23017469Seric myname = getlogin(); 23117469Seric if (myname == NULL || myname[0] == '\0') 23217469Seric { 23317469Seric 23417469Seric pw = getpwuid(getruid()); 23517469Seric if (pw != NULL) 236*40993Sbostic myname = newstr(pw->pw_name); 23717469Seric } 23819904Smiriam else 23919904Smiriam { 24019873Smiriam 241*40993Sbostic myname = newstr(myname); 242*40993Sbostic if ((pw = getpwnam(myname)) == NULL || 243*40993Sbostic getuid() != pw->pw_uid) 24419904Smiriam { 24519873Smiriam pw = getpwuid(getuid()); 24624945Seric if (pw != NULL) 247*40993Sbostic myname = newstr(pw->pw_name); 24819873Smiriam } 24919873Smiriam } 25017469Seric if (myname == NULL || myname[0] == '\0') 25117469Seric { 25217469Seric syserr("Who are you?"); 25317469Seric myname = "postmaster"; 25417469Seric } 25517469Seric } 25617469Seric 25717469Seric return (myname); 2589369Seric } 2599369Seric /* 2604190Seric ** TTYPATH -- Get the path of the user's tty 261294Seric ** 262294Seric ** Returns the pathname of the user's tty. Returns NULL if 263294Seric ** the user is not logged in or if s/he has write permission 264294Seric ** denied. 265294Seric ** 266294Seric ** Parameters: 267294Seric ** none 268294Seric ** 269294Seric ** Returns: 270294Seric ** pathname of the user's tty. 271294Seric ** NULL if not logged in or write permission denied. 272294Seric ** 273294Seric ** Side Effects: 274294Seric ** none. 275294Seric ** 276294Seric ** WARNING: 277294Seric ** Return value is in a local buffer. 278294Seric ** 279294Seric ** Called By: 280294Seric ** savemail 281294Seric */ 282294Seric 283294Seric # include <sys/stat.h> 284294Seric 285294Seric char * 286294Seric ttypath() 287294Seric { 288294Seric struct stat stbuf; 289294Seric register char *pathn; 290294Seric extern char *ttyname(); 2914081Seric extern char *getlogin(); 292294Seric 293294Seric /* compute the pathname of the controlling tty */ 2949369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 2959369Seric (pathn = ttyname(0)) == NULL) 296294Seric { 297294Seric errno = 0; 298294Seric return (NULL); 299294Seric } 300294Seric 301294Seric /* see if we have write permission */ 3022967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 303294Seric { 304294Seric errno = 0; 305294Seric return (NULL); 306294Seric } 307294Seric 308294Seric /* see if the user is logged in */ 309294Seric if (getlogin() == NULL) 310294Seric return (NULL); 311294Seric 312294Seric /* looks good */ 313294Seric return (pathn); 314294Seric } 3152967Seric /* 3162967Seric ** CHECKCOMPAT -- check for From and To person compatible. 3172967Seric ** 3182967Seric ** This routine can be supplied on a per-installation basis 3192967Seric ** to determine whether a person is allowed to send a message. 3202967Seric ** This allows restriction of certain types of internet 3212967Seric ** forwarding or registration of users. 3222967Seric ** 3232967Seric ** If the hosts are found to be incompatible, an error 3242967Seric ** message should be given using "usrerr" and FALSE should 3252967Seric ** be returned. 3262967Seric ** 3274288Seric ** 'NoReturn' can be set to suppress the return-to-sender 3284288Seric ** function; this should be done on huge messages. 3294288Seric ** 3302967Seric ** Parameters: 3312967Seric ** to -- the person being sent to. 3322967Seric ** 3332967Seric ** Returns: 3342967Seric ** TRUE -- ok to send. 3352967Seric ** FALSE -- not ok. 3362967Seric ** 3372967Seric ** Side Effects: 3382967Seric ** none (unless you include the usrerr stuff) 3392967Seric */ 3402967Seric 3412967Seric bool 3422967Seric checkcompat(to) 3432967Seric register ADDRESS *to; 3442967Seric { 34512133Seric # ifdef lint 34612133Seric if (to == NULL) 34712133Seric to++; 34812133Seric # endif lint 34910698Seric # ifdef EXAMPLE_CODE 35010698Seric /* this code is intended as an example only */ 3514437Seric register STAB *s; 3524437Seric 3534437Seric s = stab("arpa", ST_MAILER, ST_FIND); 3549369Seric if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 3559369Seric to->q_mailer == s->s_mailer) 3564437Seric { 3574437Seric usrerr("No ARPA mail through this machine: see your system administration"); 35810698Seric /* NoReturn = TRUE; to supress return copy */ 3594437Seric return (FALSE); 3604437Seric } 36110698Seric # endif EXAMPLE_CODE 3622967Seric return (TRUE); 3632967Seric } 3649369Seric /* 3659369Seric ** HOLDSIGS -- arrange to hold all signals 3669369Seric ** 3679369Seric ** Parameters: 3689369Seric ** none. 3699369Seric ** 3709369Seric ** Returns: 3719369Seric ** none. 3729369Seric ** 3739369Seric ** Side Effects: 3749369Seric ** Arranges that signals are held. 3759369Seric */ 3769369Seric 3779369Seric holdsigs() 3789369Seric { 3799369Seric } 3809369Seric /* 3819369Seric ** RLSESIGS -- arrange to release all signals 3829369Seric ** 3839369Seric ** This undoes the effect of holdsigs. 3849369Seric ** 3859369Seric ** Parameters: 3869369Seric ** none. 3879369Seric ** 3889369Seric ** Returns: 3899369Seric ** none. 3909369Seric ** 3919369Seric ** Side Effects: 3929369Seric ** Arranges that signals are released. 3939369Seric */ 3949369Seric 3959369Seric rlsesigs() 3969369Seric { 3979369Seric } 39814872Seric /* 39914872Seric ** GETLA -- get the current load average 40014872Seric ** 40114881Seric ** This code stolen from la.c. 40214881Seric ** 40314872Seric ** Parameters: 40414872Seric ** none. 40514872Seric ** 40614872Seric ** Returns: 40714872Seric ** The current load average as an integer. 40814872Seric ** 40914872Seric ** Side Effects: 41014872Seric ** none. 41114872Seric */ 41214872Seric 41338196Smckusick #ifndef sun 41414872Seric 41538196Smckusick getla() 41638196Smckusick { 41738196Smckusick double avenrun[3]; 41838196Smckusick 41938196Smckusick if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 42038196Smckusick return (0); 42138196Smckusick return ((int) (avenrun[0] + 0.5)); 42238196Smckusick } 42338196Smckusick 42438196Smckusick #else /* sun */ 42538196Smckusick 42614872Seric #include <nlist.h> 42714872Seric 42814872Seric struct nlist Nl[] = 42914872Seric { 43014872Seric { "_avenrun" }, 43114872Seric #define X_AVENRUN 0 43214872Seric { 0 }, 43314872Seric }; 43414872Seric 43540930Srick 43640930Srick extern int la; 43740930Srick 43814872Seric getla() 43914872Seric { 44014872Seric static int kmem = -1; 44124943Seric long avenrun[3]; 44225615Seric extern off_t lseek(); 44314872Seric 44414872Seric if (kmem < 0) 44514872Seric { 44624945Seric kmem = open("/dev/kmem", 0, 0); 44714872Seric if (kmem < 0) 44814872Seric return (-1); 44923118Seric (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 45014872Seric nlist("/vmunix", Nl); 45114872Seric if (Nl[0].n_type == 0) 45214872Seric return (-1); 45314872Seric } 45424945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 45523118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 45619967Seric { 45719967Seric /* thank you Ian */ 45819967Seric return (-1); 45919967Seric } 46024943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 46114872Seric } 46214872Seric 46338196Smckusick #endif /* sun */ 46424943Seric /* 46524943Seric ** SHOULDQUEUE -- should this message be queued or sent? 46624943Seric ** 46724943Seric ** Compares the message cost to the load average to decide. 46824943Seric ** 46924943Seric ** Parameters: 47024943Seric ** pri -- the priority of the message in question. 47124943Seric ** 47224943Seric ** Returns: 47324943Seric ** TRUE -- if this message should be queued up for the 47424943Seric ** time being. 47524943Seric ** FALSE -- if the load is low enough to send this message. 47624943Seric ** 47724943Seric ** Side Effects: 47824943Seric ** none. 47924943Seric */ 48024943Seric 48124943Seric bool 48224943Seric shouldqueue(pri) 48324943Seric long pri; 48424943Seric { 48524943Seric if (la < QueueLA) 48624943Seric return (FALSE); 48724943Seric return (pri > (QueueFactor / (la - QueueLA + 1))); 48824943Seric } 48924943Seric /* 49024943Seric ** SETPROCTITLE -- set process title for ps 49124943Seric ** 49224943Seric ** Parameters: 49324943Seric ** fmt -- a printf style format string. 49424943Seric ** a, b, c -- possible parameters to fmt. 49524943Seric ** 49624943Seric ** Returns: 49724943Seric ** none. 49824943Seric ** 49924943Seric ** Side Effects: 50024943Seric ** Clobbers argv of our main procedure so ps(1) will 50124943Seric ** display the title. 50224943Seric */ 50324943Seric 50424943Seric /*VARARGS1*/ 50524943Seric setproctitle(fmt, a, b, c) 50624943Seric char *fmt; 50724943Seric { 50824943Seric # ifdef SETPROCTITLE 50924943Seric register char *p; 51025049Seric register int i; 51124943Seric extern char **Argv; 51224943Seric extern char *LastArgv; 51325049Seric char buf[MAXLINE]; 51424943Seric 51525049Seric (void) sprintf(buf, fmt, a, b, c); 51624943Seric 51724943Seric /* make ps print "(sendmail)" */ 51825049Seric p = Argv[0]; 51924943Seric *p++ = '-'; 52024943Seric 52125049Seric i = strlen(buf); 52225049Seric if (i > LastArgv - p - 2) 52325049Seric { 52425049Seric i = LastArgv - p - 2; 52525049Seric buf[i] = '\0'; 52625049Seric } 52725049Seric (void) strcpy(p, buf); 52825049Seric p += i; 52924943Seric while (p < LastArgv) 53024943Seric *p++ = ' '; 53124943Seric # endif SETPROCTITLE 53224943Seric } 53325698Seric /* 53425698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 53525698Seric ** 53625698Seric ** Parameters: 53725698Seric ** none. 53825698Seric ** 53925698Seric ** Returns: 54025698Seric ** none. 54125698Seric ** 54225698Seric ** Side Effects: 54325698Seric ** Picks up extant zombies. 54425698Seric */ 54525698Seric 54625698Seric # ifdef VMUNIX 54725698Seric # include <sys/wait.h> 54825698Seric # endif VMUNIX 54925698Seric 55025698Seric reapchild() 55125698Seric { 55225698Seric # ifdef WNOHANG 55325698Seric union wait status; 55425698Seric 55525698Seric while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 55625698Seric continue; 55725698Seric # else WNOHANG 55825698Seric auto int status; 55925698Seric 56025698Seric while (wait(&status) > 0) 56125698Seric continue; 56225698Seric # endif WNOHANG 56325698Seric } 564