xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 51920)
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*51920Seric static char sccsid[] = "@(#)conf.c	5.31 (Berkeley) 12/14/91";
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;
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 
403*51920Seric /* try to guess what style of load average we have */
404*51920Seric #define LA_ZERO		1	/* always return load average as zero */
405*51920Seric #define LA_INT		2	/* read kmem for avenrun; interpret as int */
406*51920Seric #define LA_FLOAT	3	/* read kmem for avenrun; interpret as float */
407*51920Seric #define LA_SUBR		4	/* call getloadavg */
40814872Seric 
409*51920Seric #ifndef LA_TYPE
410*51920Seric #  if defined(sun)
411*51920Seric #    define LA_TYPE		LA_INT
412*51920Seric #  endif
413*51920Seric #  if defined(mips)
414*51920Seric      /* Ultrix or RISC/os */
415*51920Seric #    define LA_TYPE		LA_INT
416*51920Seric #    define LA_AVENRUN		"avenrun"
417*51920Seric #  endif
418*51920Seric #  if defined(hpux)
419*51920Seric #    define LA_TYPE		LA_FLOAT
420*51920Seric #  endif
421*51920Seric #  if defined(BSD)
422*51920Seric #    define LA_TYPE		LA_SUBR
423*51920Seric #  endif
424*51920Seric 
425*51920Seric #  ifndef LA_TYPE
426*51920Seric #    define LA_TYPE		LA_ZERO
427*51920Seric #  endif
428*51920Seric #endif
429*51920Seric 
430*51920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT)
431*51920Seric 
43214872Seric #include <nlist.h>
433*51920Seric #include <fcntl.h>
43414872Seric 
435*51920Seric #ifndef LA_AVENRUN
436*51920Seric #define LA_AVENRUN	"_avenrun"
437*51920Seric #endif
438*51920Seric 
439*51920Seric /* _PATH_UNIX should be defined in <paths.h> */
440*51920Seric #ifndef _PATH_UNIX
441*51920Seric #  if defined(hpux)
442*51920Seric #    define _PATH_UNIX		"/hp-ux"
443*51920Seric #  endif
444*51920Seric #  if defined(mips) && !defined(ultrix)
445*51920Seric      /* powerful RISC/os */
446*51920Seric #    define _PATH_UNIX		"/unix"
447*51920Seric #  endif
448*51920Seric #  ifndef _PATH_UNIX
449*51920Seric #    define _PATH_UNIX		"/vmunix"
450*51920Seric #  endif
451*51920Seric #endif
452*51920Seric 
45314872Seric struct	nlist Nl[] =
45414872Seric {
455*51920Seric 	{ LA_AVENRUN },
45614872Seric #define	X_AVENRUN	0
45714872Seric 	{ 0 },
45814872Seric };
45914872Seric 
460*51920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT)
461*51920Seric #  define FSHIFT	8
462*51920Seric #  define FSCALE	(1 << FSHIFT)
463*51920Seric #endif
46440930Srick 
46514872Seric getla()
46614872Seric {
46714872Seric 	static int kmem = -1;
468*51920Seric #if LA_TYPE == LA_INT
46924943Seric 	long avenrun[3];
470*51920Seric #else
471*51920Seric 	double avenrun[3];
472*51920Seric #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);
480*51920Seric 		(void) fcntl(kmem, F_SETFD, 1);
481*51920Seric 		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 	}
491*51920Seric #if LA_TYPE == LA_INT
49224943Seric 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
493*51920Seric #else
494*51920Seric 	return ((int) (avenrun[0] + 0.5));
495*51920Seric #endif
49614872Seric }
49714872Seric 
49851773Seric #else
499*51920Seric #if LA_TYPE == LA_SUBR
50051773Seric 
50151773Seric getla()
50251773Seric {
503*51920Seric 	double avenrun[3];
504*51920Seric 
505*51920Seric 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
506*51920Seric 		return (-1);
507*51920Seric 	return ((int) (avenrun[0] + 0.5));
50851773Seric }
50951773Seric 
51051773Seric #else
51151773Seric 
51251773Seric getla()
51351773Seric {
514*51920Seric 	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 {
540*51920Seric 	if (CurrentLA < QueueLA)
54124943Seric 		return (FALSE);
542*51920Seric 	return (pri > (QueueFactor / (CurrentLA - QueueLA + 1)));
54324943Seric }
54424943Seric /*
54524943Seric **  SETPROCTITLE -- set process title for ps
54624943Seric **
54724943Seric **	Parameters:
54824943Seric **		fmt -- a printf style format string.
54924943Seric **		a, b, c -- possible parameters to fmt.
55024943Seric **
55124943Seric **	Returns:
55224943Seric **		none.
55324943Seric **
55424943Seric **	Side Effects:
55524943Seric **		Clobbers argv of our main procedure so ps(1) will
55624943Seric **		display the title.
55724943Seric */
55824943Seric 
55924943Seric /*VARARGS1*/
56024943Seric setproctitle(fmt, a, b, c)
56124943Seric 	char *fmt;
56224943Seric {
56324943Seric # ifdef SETPROCTITLE
56424943Seric 	register char *p;
56525049Seric 	register int i;
56624943Seric 	extern char **Argv;
56724943Seric 	extern char *LastArgv;
56825049Seric 	char buf[MAXLINE];
56924943Seric 
57025049Seric 	(void) sprintf(buf, fmt, a, b, c);
57124943Seric 
57224943Seric 	/* make ps print "(sendmail)" */
57325049Seric 	p = Argv[0];
57424943Seric 	*p++ = '-';
57524943Seric 
57625049Seric 	i = strlen(buf);
57725049Seric 	if (i > LastArgv - p - 2)
57825049Seric 	{
57925049Seric 		i = LastArgv - p - 2;
58025049Seric 		buf[i] = '\0';
58125049Seric 	}
58225049Seric 	(void) strcpy(p, buf);
58325049Seric 	p += i;
58424943Seric 	while (p < LastArgv)
58524943Seric 		*p++ = ' ';
58624943Seric # endif SETPROCTITLE
58724943Seric }
58825698Seric /*
58925698Seric **  REAPCHILD -- pick up the body of my child, lest it become a zombie
59025698Seric **
59125698Seric **	Parameters:
59225698Seric **		none.
59325698Seric **
59425698Seric **	Returns:
59525698Seric **		none.
59625698Seric **
59725698Seric **	Side Effects:
59825698Seric **		Picks up extant zombies.
59925698Seric */
60025698Seric 
60125698Seric # ifdef VMUNIX
60225698Seric # include <sys/wait.h>
60325698Seric # endif VMUNIX
60425698Seric 
60546928Sbostic void
60625698Seric reapchild()
60725698Seric {
60825698Seric # ifdef WNOHANG
60925698Seric 	union wait status;
61025698Seric 
61146928Sbostic 	while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
61225698Seric 		continue;
61325698Seric # else WNOHANG
61425698Seric 	auto int status;
61525698Seric 
61646928Sbostic 	while (wait((int *)&status) > 0)
61725698Seric 		continue;
61825698Seric # endif WNOHANG
61925698Seric }
620