xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 52105)
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*52105Seric static char sccsid[] = "@(#)conf.c	5.32 (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;
148*52105Seric 	SendMode = SM_FORK;
149*52105Seric 	ErrorMode = EM_PRINT;
15040973Sbostic 	setdefuser();
15124943Seric }
152294Seric 
15340973Sbostic 
1544326Seric /*
15540973Sbostic **  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
15640973Sbostic */
15740973Sbostic 
15840973Sbostic setdefuser()
15940973Sbostic {
16040973Sbostic 	struct passwd *defpwent;
16140973Sbostic 
16240973Sbostic 	if (DefUser != NULL)
16340973Sbostic 		free(DefUser);
16440973Sbostic 	if ((defpwent = getpwuid(DefUid)) != NULL)
16540973Sbostic 		DefUser = newstr(defpwent->pw_name);
16640973Sbostic 	else
16740973Sbostic 		DefUser = newstr("nobody");
16840973Sbostic }
16940973Sbostic 
17040973Sbostic 
17140973Sbostic /*
1724326Seric **  GETRUID -- get real user id (V7)
1734326Seric */
1744326Seric 
1754326Seric getruid()
1764326Seric {
1779274Seric 	if (OpMode == MD_DAEMON)
1784536Seric 		return (RealUid);
1794536Seric 	else
1804536Seric 		return (getuid());
1814326Seric }
1824326Seric 
1834326Seric 
1844326Seric /*
1854326Seric **  GETRGID -- get real group id (V7).
1864326Seric */
1874326Seric 
1884326Seric getrgid()
1894326Seric {
1909274Seric 	if (OpMode == MD_DAEMON)
1914536Seric 		return (RealGid);
1924536Seric 	else
1934536Seric 		return (getgid());
1944326Seric }
1954326Seric 
19633936Sbostic /*
1979369Seric **  USERNAME -- return the user id of the logged in user.
1989369Seric **
1999369Seric **	Parameters:
2009369Seric **		none.
2019369Seric **
2029369Seric **	Returns:
2039369Seric **		The login name of the logged in user.
2049369Seric **
2059369Seric **	Side Effects:
2069369Seric **		none.
2079369Seric **
2089369Seric **	Notes:
2099369Seric **		The return value is statically allocated.
2109369Seric */
2119369Seric 
2129369Seric char *
2139369Seric username()
2149369Seric {
21517469Seric 	static char *myname = NULL;
2169369Seric 	extern char *getlogin();
21719904Smiriam 	register struct passwd *pw;
2189369Seric 
21917469Seric 	/* cache the result */
22017469Seric 	if (myname == NULL)
22117469Seric 	{
22217469Seric 		myname = getlogin();
22317469Seric 		if (myname == NULL || myname[0] == '\0')
22417469Seric 		{
22517469Seric 
22617469Seric 			pw = getpwuid(getruid());
22717469Seric 			if (pw != NULL)
22840993Sbostic 				myname = newstr(pw->pw_name);
22917469Seric 		}
23019904Smiriam 		else
23119904Smiriam 		{
23219873Smiriam 
23340993Sbostic 			myname = newstr(myname);
23440993Sbostic 			if ((pw = getpwnam(myname)) == NULL ||
23540993Sbostic 			      getuid() != pw->pw_uid)
23619904Smiriam 			{
23719873Smiriam 				pw = getpwuid(getuid());
23824945Seric 				if (pw != NULL)
23940993Sbostic 					myname = newstr(pw->pw_name);
24019873Smiriam 			}
24119873Smiriam 		}
24217469Seric 		if (myname == NULL || myname[0] == '\0')
24317469Seric 		{
24417469Seric 			syserr("Who are you?");
24517469Seric 			myname = "postmaster";
24617469Seric 		}
24717469Seric 	}
24817469Seric 
24917469Seric 	return (myname);
2509369Seric }
2519369Seric /*
2524190Seric **  TTYPATH -- Get the path of the user's tty
253294Seric **
254294Seric **	Returns the pathname of the user's tty.  Returns NULL if
255294Seric **	the user is not logged in or if s/he has write permission
256294Seric **	denied.
257294Seric **
258294Seric **	Parameters:
259294Seric **		none
260294Seric **
261294Seric **	Returns:
262294Seric **		pathname of the user's tty.
263294Seric **		NULL if not logged in or write permission denied.
264294Seric **
265294Seric **	Side Effects:
266294Seric **		none.
267294Seric **
268294Seric **	WARNING:
269294Seric **		Return value is in a local buffer.
270294Seric **
271294Seric **	Called By:
272294Seric **		savemail
273294Seric */
274294Seric 
275294Seric # include <sys/stat.h>
276294Seric 
277294Seric char *
278294Seric ttypath()
279294Seric {
280294Seric 	struct stat stbuf;
281294Seric 	register char *pathn;
282294Seric 	extern char *ttyname();
2834081Seric 	extern char *getlogin();
284294Seric 
285294Seric 	/* compute the pathname of the controlling tty */
2869369Seric 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
2879369Seric 	    (pathn = ttyname(0)) == NULL)
288294Seric 	{
289294Seric 		errno = 0;
290294Seric 		return (NULL);
291294Seric 	}
292294Seric 
293294Seric 	/* see if we have write permission */
2942967Seric 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
295294Seric 	{
296294Seric 		errno = 0;
297294Seric 		return (NULL);
298294Seric 	}
299294Seric 
300294Seric 	/* see if the user is logged in */
301294Seric 	if (getlogin() == NULL)
302294Seric 		return (NULL);
303294Seric 
304294Seric 	/* looks good */
305294Seric 	return (pathn);
306294Seric }
3072967Seric /*
3082967Seric **  CHECKCOMPAT -- check for From and To person compatible.
3092967Seric **
3102967Seric **	This routine can be supplied on a per-installation basis
3112967Seric **	to determine whether a person is allowed to send a message.
3122967Seric **	This allows restriction of certain types of internet
3132967Seric **	forwarding or registration of users.
3142967Seric **
3152967Seric **	If the hosts are found to be incompatible, an error
3162967Seric **	message should be given using "usrerr" and FALSE should
3172967Seric **	be returned.
3182967Seric **
3194288Seric **	'NoReturn' can be set to suppress the return-to-sender
3204288Seric **	function; this should be done on huge messages.
3214288Seric **
3222967Seric **	Parameters:
3232967Seric **		to -- the person being sent to.
3242967Seric **
3252967Seric **	Returns:
3262967Seric **		TRUE -- ok to send.
3272967Seric **		FALSE -- not ok.
3282967Seric **
3292967Seric **	Side Effects:
3302967Seric **		none (unless you include the usrerr stuff)
3312967Seric */
3322967Seric 
3332967Seric bool
3342967Seric checkcompat(to)
3352967Seric 	register ADDRESS *to;
3362967Seric {
33712133Seric # ifdef lint
33812133Seric 	if (to == NULL)
33912133Seric 		to++;
34012133Seric # endif lint
34110698Seric # ifdef EXAMPLE_CODE
34210698Seric 	/* this code is intended as an example only */
3434437Seric 	register STAB *s;
3444437Seric 
3454437Seric 	s = stab("arpa", ST_MAILER, ST_FIND);
3469369Seric 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
3479369Seric 	    to->q_mailer == s->s_mailer)
3484437Seric 	{
3494437Seric 		usrerr("No ARPA mail through this machine: see your system administration");
35010698Seric 		/* NoReturn = TRUE; to supress return copy */
3514437Seric 		return (FALSE);
3524437Seric 	}
35310698Seric # endif EXAMPLE_CODE
3542967Seric 	return (TRUE);
3552967Seric }
3569369Seric /*
3579369Seric **  HOLDSIGS -- arrange to hold all signals
3589369Seric **
3599369Seric **	Parameters:
3609369Seric **		none.
3619369Seric **
3629369Seric **	Returns:
3639369Seric **		none.
3649369Seric **
3659369Seric **	Side Effects:
3669369Seric **		Arranges that signals are held.
3679369Seric */
3689369Seric 
3699369Seric holdsigs()
3709369Seric {
3719369Seric }
3729369Seric /*
3739369Seric **  RLSESIGS -- arrange to release all signals
3749369Seric **
3759369Seric **	This undoes the effect of holdsigs.
3769369Seric **
3779369Seric **	Parameters:
3789369Seric **		none.
3799369Seric **
3809369Seric **	Returns:
3819369Seric **		none.
3829369Seric **
3839369Seric **	Side Effects:
3849369Seric **		Arranges that signals are released.
3859369Seric */
3869369Seric 
3879369Seric rlsesigs()
3889369Seric {
3899369Seric }
39014872Seric /*
39114872Seric **  GETLA -- get the current load average
39214872Seric **
39314881Seric **	This code stolen from la.c.
39414881Seric **
39514872Seric **	Parameters:
39614872Seric **		none.
39714872Seric **
39814872Seric **	Returns:
39914872Seric **		The current load average as an integer.
40014872Seric **
40114872Seric **	Side Effects:
40214872Seric **		none.
40314872Seric */
40414872Seric 
40551920Seric /* try to guess what style of load average we have */
40651920Seric #define LA_ZERO		1	/* always return load average as zero */
40751920Seric #define LA_INT		2	/* read kmem for avenrun; interpret as int */
40851920Seric #define LA_FLOAT	3	/* read kmem for avenrun; interpret as float */
40951920Seric #define LA_SUBR		4	/* call getloadavg */
41014872Seric 
41151920Seric #ifndef LA_TYPE
41251920Seric #  if defined(sun)
41351920Seric #    define LA_TYPE		LA_INT
41451920Seric #  endif
41551920Seric #  if defined(mips)
41651920Seric      /* Ultrix or RISC/os */
41751920Seric #    define LA_TYPE		LA_INT
41851920Seric #    define LA_AVENRUN		"avenrun"
41951920Seric #  endif
42051920Seric #  if defined(hpux)
42151920Seric #    define LA_TYPE		LA_FLOAT
42251920Seric #  endif
42351920Seric #  if defined(BSD)
42451920Seric #    define LA_TYPE		LA_SUBR
42551920Seric #  endif
42651920Seric 
42751920Seric #  ifndef LA_TYPE
42851920Seric #    define LA_TYPE		LA_ZERO
42951920Seric #  endif
43051920Seric #endif
43151920Seric 
43251920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT)
43351920Seric 
43414872Seric #include <nlist.h>
43551920Seric #include <fcntl.h>
43614872Seric 
43751920Seric #ifndef LA_AVENRUN
43851920Seric #define LA_AVENRUN	"_avenrun"
43951920Seric #endif
44051920Seric 
44151920Seric /* _PATH_UNIX should be defined in <paths.h> */
44251920Seric #ifndef _PATH_UNIX
44351920Seric #  if defined(hpux)
44451920Seric #    define _PATH_UNIX		"/hp-ux"
44551920Seric #  endif
44651920Seric #  if defined(mips) && !defined(ultrix)
44751920Seric      /* powerful RISC/os */
44851920Seric #    define _PATH_UNIX		"/unix"
44951920Seric #  endif
45051920Seric #  ifndef _PATH_UNIX
45151920Seric #    define _PATH_UNIX		"/vmunix"
45251920Seric #  endif
45351920Seric #endif
45451920Seric 
45514872Seric struct	nlist Nl[] =
45614872Seric {
45751920Seric 	{ LA_AVENRUN },
45814872Seric #define	X_AVENRUN	0
45914872Seric 	{ 0 },
46014872Seric };
46114872Seric 
46251920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT)
46351920Seric #  define FSHIFT	8
46451920Seric #  define FSCALE	(1 << FSHIFT)
46551920Seric #endif
46640930Srick 
46714872Seric getla()
46814872Seric {
46914872Seric 	static int kmem = -1;
47051920Seric #if LA_TYPE == LA_INT
47124943Seric 	long avenrun[3];
47251920Seric #else
47351920Seric 	double avenrun[3];
47451920Seric #endif
47525615Seric 	extern off_t lseek();
47614872Seric 
47714872Seric 	if (kmem < 0)
47814872Seric 	{
47924945Seric 		kmem = open("/dev/kmem", 0, 0);
48014872Seric 		if (kmem < 0)
48114872Seric 			return (-1);
48251920Seric 		(void) fcntl(kmem, F_SETFD, 1);
48351920Seric 		nlist(_PATH_UNIX, Nl);
48414872Seric 		if (Nl[0].n_type == 0)
48514872Seric 			return (-1);
48614872Seric 	}
48724945Seric 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
48823118Seric 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
48919967Seric 	{
49019967Seric 		/* thank you Ian */
49119967Seric 		return (-1);
49219967Seric 	}
49351920Seric #if LA_TYPE == LA_INT
49424943Seric 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
49551920Seric #else
49651920Seric 	return ((int) (avenrun[0] + 0.5));
49751920Seric #endif
49814872Seric }
49914872Seric 
50051773Seric #else
50151920Seric #if LA_TYPE == LA_SUBR
50251773Seric 
50351773Seric getla()
50451773Seric {
50551920Seric 	double avenrun[3];
50651920Seric 
50751920Seric 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
50851920Seric 		return (-1);
50951920Seric 	return ((int) (avenrun[0] + 0.5));
51051773Seric }
51151773Seric 
51251773Seric #else
51351773Seric 
51451773Seric getla()
51551773Seric {
51651920Seric 	return (0);
51751773Seric }
51851773Seric 
51951773Seric #endif
52051773Seric #endif
52124943Seric /*
52224943Seric **  SHOULDQUEUE -- should this message be queued or sent?
52324943Seric **
52424943Seric **	Compares the message cost to the load average to decide.
52524943Seric **
52624943Seric **	Parameters:
52724943Seric **		pri -- the priority of the message in question.
52824943Seric **
52924943Seric **	Returns:
53024943Seric **		TRUE -- if this message should be queued up for the
53124943Seric **			time being.
53224943Seric **		FALSE -- if the load is low enough to send this message.
53324943Seric **
53424943Seric **	Side Effects:
53524943Seric **		none.
53624943Seric */
53724943Seric 
53824943Seric bool
53924943Seric shouldqueue(pri)
54024943Seric 	long pri;
54124943Seric {
54251920Seric 	if (CurrentLA < QueueLA)
54324943Seric 		return (FALSE);
54451920Seric 	return (pri > (QueueFactor / (CurrentLA - QueueLA + 1)));
54524943Seric }
54624943Seric /*
54724943Seric **  SETPROCTITLE -- set process title for ps
54824943Seric **
54924943Seric **	Parameters:
55024943Seric **		fmt -- a printf style format string.
55124943Seric **		a, b, c -- possible parameters to fmt.
55224943Seric **
55324943Seric **	Returns:
55424943Seric **		none.
55524943Seric **
55624943Seric **	Side Effects:
55724943Seric **		Clobbers argv of our main procedure so ps(1) will
55824943Seric **		display the title.
55924943Seric */
56024943Seric 
56124943Seric /*VARARGS1*/
56224943Seric setproctitle(fmt, a, b, c)
56324943Seric 	char *fmt;
56424943Seric {
56524943Seric # ifdef SETPROCTITLE
56624943Seric 	register char *p;
56725049Seric 	register int i;
56824943Seric 	extern char **Argv;
56924943Seric 	extern char *LastArgv;
57025049Seric 	char buf[MAXLINE];
57124943Seric 
57225049Seric 	(void) sprintf(buf, fmt, a, b, c);
57324943Seric 
57424943Seric 	/* make ps print "(sendmail)" */
57525049Seric 	p = Argv[0];
57624943Seric 	*p++ = '-';
57724943Seric 
57825049Seric 	i = strlen(buf);
57925049Seric 	if (i > LastArgv - p - 2)
58025049Seric 	{
58125049Seric 		i = LastArgv - p - 2;
58225049Seric 		buf[i] = '\0';
58325049Seric 	}
58425049Seric 	(void) strcpy(p, buf);
58525049Seric 	p += i;
58624943Seric 	while (p < LastArgv)
58724943Seric 		*p++ = ' ';
58824943Seric # endif SETPROCTITLE
58924943Seric }
59025698Seric /*
59125698Seric **  REAPCHILD -- pick up the body of my child, lest it become a zombie
59225698Seric **
59325698Seric **	Parameters:
59425698Seric **		none.
59525698Seric **
59625698Seric **	Returns:
59725698Seric **		none.
59825698Seric **
59925698Seric **	Side Effects:
60025698Seric **		Picks up extant zombies.
60125698Seric */
60225698Seric 
60325698Seric # ifdef VMUNIX
60425698Seric # include <sys/wait.h>
60525698Seric # endif VMUNIX
60625698Seric 
60746928Sbostic void
60825698Seric reapchild()
60925698Seric {
61025698Seric # ifdef WNOHANG
61125698Seric 	union wait status;
61225698Seric 
61346928Sbostic 	while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
61425698Seric 		continue;
61525698Seric # else WNOHANG
61625698Seric 	auto int status;
61725698Seric 
61846928Sbostic 	while (wait((int *)&status) > 0)
61925698Seric 		continue;
62025698Seric # endif WNOHANG
62125698Seric }
622