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*40973Sbostic static char sccsid[] = "@(#)conf.c 5.23 (Berkeley) 04/18/90"; 2133728Sbostic #endif /* not lint */ 2222698Sdist 2314881Seric # include <sys/ioctl.h> 2424943Seric # include <sys/param.h> 2536928Sbostic # include <pwd.h> 263309Seric # include "sendmail.h" 27404Seric 28294Seric /* 293309Seric ** CONF.C -- Sendmail Configuration Tables. 30294Seric ** 31294Seric ** Defines the configuration of this installation. 32294Seric ** 331388Seric ** Compilation Flags: 3414872Seric ** VMUNIX -- running on a Berkeley UNIX system. 35294Seric ** 361388Seric ** Configuration Variables: 372897Seric ** HdrInfo -- a table describing well-known header fields. 382897Seric ** Each entry has the field name and some flags, 394147Seric ** which are described in sendmail.h. 404093Seric ** 414093Seric ** Notes: 424093Seric ** I have tried to put almost all the reasonable 434093Seric ** configuration information into the configuration 444093Seric ** file read at runtime. My intent is that anything 454093Seric ** here is a function of the version of UNIX you 464093Seric ** are running, or is really static -- for example 474093Seric ** the headers are a superset of widely used 484093Seric ** protocols. If you find yourself playing with 494093Seric ** this file too much, you may be making a mistake! 50294Seric */ 51294Seric 52294Seric 53294Seric 54294Seric 554437Seric /* 562897Seric ** Header info table 573057Seric ** Final (null) entry contains the flags used for any other field. 584147Seric ** 594147Seric ** Not all of these are actually handled specially by sendmail 604147Seric ** at this time. They are included as placeholders, to let 614147Seric ** you know that "someday" I intend to have sendmail do 624147Seric ** something with them. 632897Seric */ 642897Seric 652897Seric struct hdrinfo HdrInfo[] = 662897Seric { 678060Seric /* originator fields, most to least significant */ 6811417Seric "resent-sender", H_FROM|H_RESENT, 6911417Seric "resent-from", H_FROM|H_RESENT, 7025686Seric "resent-reply-to", H_FROM|H_RESENT, 719055Seric "sender", H_FROM, 729055Seric "from", H_FROM, 7325686Seric "reply-to", H_FROM, 749055Seric "full-name", H_ACHECK, 759055Seric "return-receipt-to", H_FROM, 769055Seric "errors-to", H_FROM, 778060Seric /* destination fields */ 789055Seric "to", H_RCPT, 7911417Seric "resent-to", H_RCPT|H_RESENT, 809055Seric "cc", H_RCPT, 8111417Seric "resent-cc", H_RCPT|H_RESENT, 829055Seric "bcc", H_RCPT|H_ACHECK, 8311417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 848060Seric /* message identification and control */ 8511417Seric "message-id", 0, 8611417Seric "resent-message-id", H_RESENT, 879055Seric "message", H_EOH, 889055Seric "text", H_EOH, 8911417Seric /* date fields */ 9011417Seric "date", 0, 9111417Seric "resent-date", H_RESENT, 928060Seric /* trace fields */ 939055Seric "received", H_TRACE|H_FORCE, 949055Seric "via", H_TRACE|H_FORCE, 959055Seric "mail-from", H_TRACE|H_FORCE, 968060Seric 979055Seric NULL, 0, 982897Seric }; 994166Seric 1004166Seric 1014166Seric /* 1024166Seric ** ARPANET error message numbers. 1034166Seric */ 1044166Seric 1057956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 1067956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 1077956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 1087956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 1094282Seric 1104282Seric 1114282Seric 1124282Seric /* 1134282Seric ** Location of system files/databases/etc. 1144282Seric */ 1154282Seric 11637972Sbostic char *ConfFile = "/etc/sendmail.cf"; /* runtime configuration */ 11737972Sbostic char *FreezeFile = "/etc/sendmail.fc"; /* frozen version of above */ 1189039Seric 1199064Seric 1209064Seric 1219039Seric /* 12224943Seric ** Miscellaneous stuff. 1239039Seric */ 1249039Seric 12524943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 12640938Srick extern int la; /* load average */ 12724943Seric /* 12824943Seric ** SETDEFAULTS -- set default values 12924943Seric ** 13024943Seric ** Because of the way freezing is done, these must be initialized 13124943Seric ** using direct code. 13224943Seric ** 13324943Seric ** Parameters: 13424943Seric ** none. 13524943Seric ** 13624943Seric ** Returns: 13724943Seric ** none. 13824943Seric ** 13924943Seric ** Side Effects: 14024943Seric ** Initializes a bunch of global variables to their 14124943Seric ** default values. 14224943Seric */ 14324943Seric 14424943Seric setdefaults() 14524943Seric { 14624943Seric QueueLA = 8; 14724943Seric QueueFactor = 10000; 14824943Seric RefuseLA = 12; 14924943Seric SpaceSub = ' '; 15024981Seric WkRecipFact = 1000; 15124981Seric WkClassFact = 1800; 15225812Seric WkTimeFact = 9000; 15324981Seric FileMode = 0644; 15424981Seric DefUid = 1; 15524981Seric DefGid = 1; 156*40973Sbostic setdefuser(); 15724943Seric } 158294Seric 159*40973Sbostic 1604326Seric /* 161*40973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 162*40973Sbostic */ 163*40973Sbostic 164*40973Sbostic setdefuser() 165*40973Sbostic { 166*40973Sbostic struct passwd *defpwent; 167*40973Sbostic 168*40973Sbostic if (DefUser != NULL) 169*40973Sbostic free(DefUser); 170*40973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 171*40973Sbostic DefUser = newstr(defpwent->pw_name); 172*40973Sbostic else 173*40973Sbostic DefUser = newstr("nobody"); 174*40973Sbostic } 175*40973Sbostic 176*40973Sbostic 177*40973Sbostic /* 1784326Seric ** GETRUID -- get real user id (V7) 1794326Seric */ 1804326Seric 1814326Seric getruid() 1824326Seric { 1839274Seric if (OpMode == MD_DAEMON) 1844536Seric return (RealUid); 1854536Seric else 1864536Seric return (getuid()); 1874326Seric } 1884326Seric 1894326Seric 1904326Seric /* 1914326Seric ** GETRGID -- get real group id (V7). 1924326Seric */ 1934326Seric 1944326Seric getrgid() 1954326Seric { 1969274Seric if (OpMode == MD_DAEMON) 1974536Seric return (RealGid); 1984536Seric else 1994536Seric return (getgid()); 2004326Seric } 2014326Seric 20233936Sbostic /* 2039369Seric ** USERNAME -- return the user id of the logged in user. 2049369Seric ** 2059369Seric ** Parameters: 2069369Seric ** none. 2079369Seric ** 2089369Seric ** Returns: 2099369Seric ** The login name of the logged in user. 2109369Seric ** 2119369Seric ** Side Effects: 2129369Seric ** none. 2139369Seric ** 2149369Seric ** Notes: 2159369Seric ** The return value is statically allocated. 2169369Seric */ 2179369Seric 2189369Seric char * 2199369Seric username() 2209369Seric { 22117469Seric static char *myname = NULL; 2229369Seric extern char *getlogin(); 22319904Smiriam register struct passwd *pw; 22419904Smiriam extern struct passwd *getpwuid(); 2259369Seric 22617469Seric /* cache the result */ 22717469Seric if (myname == NULL) 22817469Seric { 22917469Seric myname = getlogin(); 23017469Seric if (myname == NULL || myname[0] == '\0') 23117469Seric { 23217469Seric 23317469Seric pw = getpwuid(getruid()); 23417469Seric if (pw != NULL) 23517469Seric myname = pw->pw_name; 23617469Seric } 23719904Smiriam else 23819904Smiriam { 23919873Smiriam 24019873Smiriam pw = getpwnam(myname); 24119904Smiriam if(getuid() != pw->pw_uid) 24219904Smiriam { 24319873Smiriam pw = getpwuid(getuid()); 24424945Seric if (pw != NULL) 24524945Seric myname = pw->pw_name; 24619873Smiriam } 24719873Smiriam } 24817469Seric if (myname == NULL || myname[0] == '\0') 24917469Seric { 25017469Seric syserr("Who are you?"); 25117469Seric myname = "postmaster"; 25217469Seric } 25317469Seric } 25417469Seric 25517469Seric return (myname); 2569369Seric } 2579369Seric /* 2584190Seric ** TTYPATH -- Get the path of the user's tty 259294Seric ** 260294Seric ** Returns the pathname of the user's tty. Returns NULL if 261294Seric ** the user is not logged in or if s/he has write permission 262294Seric ** denied. 263294Seric ** 264294Seric ** Parameters: 265294Seric ** none 266294Seric ** 267294Seric ** Returns: 268294Seric ** pathname of the user's tty. 269294Seric ** NULL if not logged in or write permission denied. 270294Seric ** 271294Seric ** Side Effects: 272294Seric ** none. 273294Seric ** 274294Seric ** WARNING: 275294Seric ** Return value is in a local buffer. 276294Seric ** 277294Seric ** Called By: 278294Seric ** savemail 279294Seric */ 280294Seric 281294Seric # include <sys/stat.h> 282294Seric 283294Seric char * 284294Seric ttypath() 285294Seric { 286294Seric struct stat stbuf; 287294Seric register char *pathn; 288294Seric extern char *ttyname(); 2894081Seric extern char *getlogin(); 290294Seric 291294Seric /* compute the pathname of the controlling tty */ 2929369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 2939369Seric (pathn = ttyname(0)) == NULL) 294294Seric { 295294Seric errno = 0; 296294Seric return (NULL); 297294Seric } 298294Seric 299294Seric /* see if we have write permission */ 3002967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 301294Seric { 302294Seric errno = 0; 303294Seric return (NULL); 304294Seric } 305294Seric 306294Seric /* see if the user is logged in */ 307294Seric if (getlogin() == NULL) 308294Seric return (NULL); 309294Seric 310294Seric /* looks good */ 311294Seric return (pathn); 312294Seric } 3132967Seric /* 3142967Seric ** CHECKCOMPAT -- check for From and To person compatible. 3152967Seric ** 3162967Seric ** This routine can be supplied on a per-installation basis 3172967Seric ** to determine whether a person is allowed to send a message. 3182967Seric ** This allows restriction of certain types of internet 3192967Seric ** forwarding or registration of users. 3202967Seric ** 3212967Seric ** If the hosts are found to be incompatible, an error 3222967Seric ** message should be given using "usrerr" and FALSE should 3232967Seric ** be returned. 3242967Seric ** 3254288Seric ** 'NoReturn' can be set to suppress the return-to-sender 3264288Seric ** function; this should be done on huge messages. 3274288Seric ** 3282967Seric ** Parameters: 3292967Seric ** to -- the person being sent to. 3302967Seric ** 3312967Seric ** Returns: 3322967Seric ** TRUE -- ok to send. 3332967Seric ** FALSE -- not ok. 3342967Seric ** 3352967Seric ** Side Effects: 3362967Seric ** none (unless you include the usrerr stuff) 3372967Seric */ 3382967Seric 3392967Seric bool 3402967Seric checkcompat(to) 3412967Seric register ADDRESS *to; 3422967Seric { 34312133Seric # ifdef lint 34412133Seric if (to == NULL) 34512133Seric to++; 34612133Seric # endif lint 34710698Seric # ifdef EXAMPLE_CODE 34810698Seric /* this code is intended as an example only */ 3494437Seric register STAB *s; 3504437Seric 3514437Seric s = stab("arpa", ST_MAILER, ST_FIND); 3529369Seric if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 3539369Seric to->q_mailer == s->s_mailer) 3544437Seric { 3554437Seric usrerr("No ARPA mail through this machine: see your system administration"); 35610698Seric /* NoReturn = TRUE; to supress return copy */ 3574437Seric return (FALSE); 3584437Seric } 35910698Seric # endif EXAMPLE_CODE 3602967Seric return (TRUE); 3612967Seric } 3629369Seric /* 3639369Seric ** HOLDSIGS -- arrange to hold all signals 3649369Seric ** 3659369Seric ** Parameters: 3669369Seric ** none. 3679369Seric ** 3689369Seric ** Returns: 3699369Seric ** none. 3709369Seric ** 3719369Seric ** Side Effects: 3729369Seric ** Arranges that signals are held. 3739369Seric */ 3749369Seric 3759369Seric holdsigs() 3769369Seric { 3779369Seric } 3789369Seric /* 3799369Seric ** RLSESIGS -- arrange to release all signals 3809369Seric ** 3819369Seric ** This undoes the effect of holdsigs. 3829369Seric ** 3839369Seric ** Parameters: 3849369Seric ** none. 3859369Seric ** 3869369Seric ** Returns: 3879369Seric ** none. 3889369Seric ** 3899369Seric ** Side Effects: 3909369Seric ** Arranges that signals are released. 3919369Seric */ 3929369Seric 3939369Seric rlsesigs() 3949369Seric { 3959369Seric } 39614872Seric /* 39714872Seric ** GETLA -- get the current load average 39814872Seric ** 39914881Seric ** This code stolen from la.c. 40014881Seric ** 40114872Seric ** Parameters: 40214872Seric ** none. 40314872Seric ** 40414872Seric ** Returns: 40514872Seric ** The current load average as an integer. 40614872Seric ** 40714872Seric ** Side Effects: 40814872Seric ** none. 40914872Seric */ 41014872Seric 41138196Smckusick #ifndef sun 41214872Seric 41338196Smckusick getla() 41438196Smckusick { 41538196Smckusick double avenrun[3]; 41638196Smckusick 41738196Smckusick if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 41838196Smckusick return (0); 41938196Smckusick return ((int) (avenrun[0] + 0.5)); 42038196Smckusick } 42138196Smckusick 42238196Smckusick #else /* sun */ 42338196Smckusick 42414872Seric #include <nlist.h> 42514872Seric 42614872Seric struct nlist Nl[] = 42714872Seric { 42814872Seric { "_avenrun" }, 42914872Seric #define X_AVENRUN 0 43014872Seric { 0 }, 43114872Seric }; 43214872Seric 43340930Srick 43440930Srick extern int la; 43540930Srick 43614872Seric getla() 43714872Seric { 43814872Seric static int kmem = -1; 43924943Seric long avenrun[3]; 44025615Seric extern off_t lseek(); 44114872Seric 44214872Seric if (kmem < 0) 44314872Seric { 44424945Seric kmem = open("/dev/kmem", 0, 0); 44514872Seric if (kmem < 0) 44614872Seric return (-1); 44723118Seric (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 44814872Seric nlist("/vmunix", Nl); 44914872Seric if (Nl[0].n_type == 0) 45014872Seric return (-1); 45114872Seric } 45224945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 45323118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 45419967Seric { 45519967Seric /* thank you Ian */ 45619967Seric return (-1); 45719967Seric } 45824943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 45914872Seric } 46014872Seric 46138196Smckusick #endif /* sun */ 46224943Seric /* 46324943Seric ** SHOULDQUEUE -- should this message be queued or sent? 46424943Seric ** 46524943Seric ** Compares the message cost to the load average to decide. 46624943Seric ** 46724943Seric ** Parameters: 46824943Seric ** pri -- the priority of the message in question. 46924943Seric ** 47024943Seric ** Returns: 47124943Seric ** TRUE -- if this message should be queued up for the 47224943Seric ** time being. 47324943Seric ** FALSE -- if the load is low enough to send this message. 47424943Seric ** 47524943Seric ** Side Effects: 47624943Seric ** none. 47724943Seric */ 47824943Seric 47924943Seric bool 48024943Seric shouldqueue(pri) 48124943Seric long pri; 48224943Seric { 48324943Seric if (la < QueueLA) 48424943Seric return (FALSE); 48524943Seric return (pri > (QueueFactor / (la - QueueLA + 1))); 48624943Seric } 48724943Seric /* 48824943Seric ** SETPROCTITLE -- set process title for ps 48924943Seric ** 49024943Seric ** Parameters: 49124943Seric ** fmt -- a printf style format string. 49224943Seric ** a, b, c -- possible parameters to fmt. 49324943Seric ** 49424943Seric ** Returns: 49524943Seric ** none. 49624943Seric ** 49724943Seric ** Side Effects: 49824943Seric ** Clobbers argv of our main procedure so ps(1) will 49924943Seric ** display the title. 50024943Seric */ 50124943Seric 50224943Seric /*VARARGS1*/ 50324943Seric setproctitle(fmt, a, b, c) 50424943Seric char *fmt; 50524943Seric { 50624943Seric # ifdef SETPROCTITLE 50724943Seric register char *p; 50825049Seric register int i; 50924943Seric extern char **Argv; 51024943Seric extern char *LastArgv; 51125049Seric char buf[MAXLINE]; 51224943Seric 51325049Seric (void) sprintf(buf, fmt, a, b, c); 51424943Seric 51524943Seric /* make ps print "(sendmail)" */ 51625049Seric p = Argv[0]; 51724943Seric *p++ = '-'; 51824943Seric 51925049Seric i = strlen(buf); 52025049Seric if (i > LastArgv - p - 2) 52125049Seric { 52225049Seric i = LastArgv - p - 2; 52325049Seric buf[i] = '\0'; 52425049Seric } 52525049Seric (void) strcpy(p, buf); 52625049Seric p += i; 52724943Seric while (p < LastArgv) 52824943Seric *p++ = ' '; 52924943Seric # endif SETPROCTITLE 53024943Seric } 53125698Seric /* 53225698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 53325698Seric ** 53425698Seric ** Parameters: 53525698Seric ** none. 53625698Seric ** 53725698Seric ** Returns: 53825698Seric ** none. 53925698Seric ** 54025698Seric ** Side Effects: 54125698Seric ** Picks up extant zombies. 54225698Seric */ 54325698Seric 54425698Seric # ifdef VMUNIX 54525698Seric # include <sys/wait.h> 54625698Seric # endif VMUNIX 54725698Seric 54825698Seric reapchild() 54925698Seric { 55025698Seric # ifdef WNOHANG 55125698Seric union wait status; 55225698Seric 55325698Seric while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 55425698Seric continue; 55525698Seric # else WNOHANG 55625698Seric auto int status; 55725698Seric 55825698Seric while (wait(&status) > 0) 55925698Seric continue; 56025698Seric # endif WNOHANG 56125698Seric } 562