xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 24943)
122698Sdist /*
222698Sdist **  Sendmail
322698Sdist **  Copyright (c) 1983  Eric P. Allman
422698Sdist **  Berkeley, California
522698Sdist **
622698Sdist **  Copyright (c) 1983 Regents of the University of California.
722698Sdist **  All rights reserved.  The Berkeley software License Agreement
822698Sdist **  specifies the terms and conditions for redistribution.
922698Sdist */
1022698Sdist 
1122698Sdist #ifndef lint
12*24943Seric static char	SccsId[] = "@(#)conf.c	5.3.1.1 (Berkeley) 09/19/85";
1322698Sdist #endif not lint
1422698Sdist 
15294Seric # include <pwd.h>
1614881Seric # include <sys/ioctl.h>
17*24943Seric # ifdef sun
18*24943Seric # include <sys/param.h>
19*24943Seric # endif sun
203309Seric # include "sendmail.h"
21404Seric 
22294Seric /*
233309Seric **  CONF.C -- Sendmail Configuration Tables.
24294Seric **
25294Seric **	Defines the configuration of this installation.
26294Seric **
271388Seric **	Compilation Flags:
281388Seric **		V6 -- running on a version 6 system.  This determines
291388Seric **			whether to define certain routines between
301388Seric **			the two systems.  If you are running a funny
311388Seric **			system, e.g., V6 with long tty names, this
321388Seric **			should be checked carefully.
3314872Seric **		VMUNIX -- running on a Berkeley UNIX system.
34294Seric **
351388Seric **	Configuration Variables:
362897Seric **		HdrInfo -- a table describing well-known header fields.
372897Seric **			Each entry has the field name and some flags,
384147Seric **			which are described in sendmail.h.
394093Seric **
404093Seric **	Notes:
414093Seric **		I have tried to put almost all the reasonable
424093Seric **		configuration information into the configuration
434093Seric **		file read at runtime.  My intent is that anything
444093Seric **		here is a function of the version of UNIX you
454093Seric **		are running, or is really static -- for example
464093Seric **		the headers are a superset of widely used
474093Seric **		protocols.  If you find yourself playing with
484093Seric **		this file too much, you may be making a mistake!
49294Seric */
50294Seric 
51294Seric 
52294Seric 
53294Seric 
544437Seric /*
552897Seric **  Header info table
563057Seric **	Final (null) entry contains the flags used for any other field.
574147Seric **
584147Seric **	Not all of these are actually handled specially by sendmail
594147Seric **	at this time.  They are included as placeholders, to let
604147Seric **	you know that "someday" I intend to have sendmail do
614147Seric **	something with them.
622897Seric */
632897Seric 
642897Seric struct hdrinfo	HdrInfo[] =
652897Seric {
668060Seric 		/* originator fields, most to least significant  */
6711417Seric 	"resent-sender",	H_FROM|H_RESENT,
6811417Seric 	"resent-from",		H_FROM|H_RESENT,
699055Seric 	"sender",		H_FROM,
709055Seric 	"from",			H_FROM,
719055Seric 	"full-name",		H_ACHECK,
729055Seric 	"return-receipt-to",	H_FROM,
739055Seric 	"errors-to",		H_FROM,
748060Seric 		/* destination fields */
759055Seric 	"to",			H_RCPT,
7611417Seric 	"resent-to",		H_RCPT|H_RESENT,
779055Seric 	"cc",			H_RCPT,
7811417Seric 	"resent-cc",		H_RCPT|H_RESENT,
799055Seric 	"bcc",			H_RCPT|H_ACHECK,
8011417Seric 	"resent-bcc",		H_RCPT|H_ACHECK|H_RESENT,
818060Seric 		/* message identification and control */
8211417Seric 	"message-id",		0,
8311417Seric 	"resent-message-id",	H_RESENT,
849055Seric 	"message",		H_EOH,
859055Seric 	"text",			H_EOH,
8611417Seric 		/* date fields */
8711417Seric 	"date",			0,
8811417Seric 	"resent-date",		H_RESENT,
898060Seric 		/* trace fields */
909055Seric 	"received",		H_TRACE|H_FORCE,
919055Seric 	"via",			H_TRACE|H_FORCE,
929055Seric 	"mail-from",		H_TRACE|H_FORCE,
938060Seric 
949055Seric 	NULL,			0,
952897Seric };
964166Seric 
974166Seric 
984166Seric /*
994166Seric **  ARPANET error message numbers.
1004166Seric */
1014166Seric 
1027956Seric char	Arpa_Info[] =		"050";	/* arbitrary info */
1037956Seric char	Arpa_TSyserr[] =	"451";	/* some (transient) system error */
1047956Seric char	Arpa_PSyserr[] =	"554";	/* some (permanent) system error */
1057956Seric char	Arpa_Usrerr[] =		"554";	/* some (fatal) user error */
1064282Seric 
1074282Seric 
1084282Seric 
1094282Seric /*
1104282Seric **  Location of system files/databases/etc.
1114282Seric */
1124282Seric 
1134282Seric char	*ConfFile =	"/usr/lib/sendmail.cf";	/* runtime configuration */
1149064Seric char	*FreezeFile =	"/usr/lib/sendmail.fc";	/* frozen version of above */
1159039Seric 
1169064Seric 
1179064Seric 
1189039Seric /*
119*24943Seric **  Miscellaneous stuff.
1209039Seric */
1219039Seric 
122*24943Seric int	DtableSize =	50;		/* max open files; reset in 4.2bsd */
123*24943Seric /*
124*24943Seric **  SETDEFAULTS -- set default values
125*24943Seric **
126*24943Seric **	Because of the way freezing is done, these must be initialized
127*24943Seric **	using direct code.
128*24943Seric **
129*24943Seric **	Parameters:
130*24943Seric **		none.
131*24943Seric **
132*24943Seric **	Returns:
133*24943Seric **		none.
134*24943Seric **
135*24943Seric **	Side Effects:
136*24943Seric **		Initializes a bunch of global variables to their
137*24943Seric **		default values.
138*24943Seric */
139*24943Seric 
140*24943Seric setdefaults()
141*24943Seric {
142*24943Seric 	QueueLA = 8;
143*24943Seric 	QueueFactor = 10000;
144*24943Seric 	RefuseLA = 12;
145*24943Seric 	SpaceSub = ' ';
146*24943Seric }
147294Seric 
148294Seric # ifdef V6
149294Seric /*
1504190Seric **  TTYNAME -- return name of terminal.
151294Seric **
152294Seric **	Parameters:
1534190Seric **		fd -- file descriptor to check.
154294Seric **
155294Seric **	Returns:
1564190Seric **		pointer to full path of tty.
1574190Seric **		NULL if no tty.
158294Seric **
159294Seric **	Side Effects:
160294Seric **		none.
161294Seric */
162294Seric 
163294Seric char *
1644190Seric ttyname(fd)
1654190Seric 	int fd;
166294Seric {
1674190Seric 	register char tn;
168294Seric 	static char pathn[] = "/dev/ttyx";
169294Seric 
170294Seric 	/* compute the pathname of the controlling tty */
1714190Seric 	if ((tn = ttyn(fd)) == NULL)
172294Seric 	{
173294Seric 		errno = 0;
174294Seric 		return (NULL);
175294Seric 	}
1764190Seric 	pathn[8] = tn;
177294Seric 	return (pathn);
178294Seric }
179294Seric /*
180294Seric **  FDOPEN -- Open a stdio file given an open file descriptor.
181294Seric **
182294Seric **	This is included here because it is standard in v7, but we
183294Seric **	need it in v6.
184294Seric **
185294Seric **	Algorithm:
186294Seric **		Open /dev/null to create a descriptor.
187294Seric **		Close that descriptor.
188294Seric **		Copy the existing fd into the descriptor.
189294Seric **
190294Seric **	Parameters:
191294Seric **		fd -- the open file descriptor.
192294Seric **		type -- "r", "w", or whatever.
193294Seric **
194294Seric **	Returns:
195294Seric **		The file descriptor it creates.
196294Seric **
197294Seric **	Side Effects:
198294Seric **		none
199294Seric **
200294Seric **	Called By:
201294Seric **		deliver
202294Seric **
203294Seric **	Notes:
204294Seric **		The mode of fd must match "type".
205294Seric */
206294Seric 
207294Seric FILE *
208294Seric fdopen(fd, type)
209294Seric 	int fd;
210294Seric 	char *type;
211294Seric {
212294Seric 	register FILE *f;
213294Seric 
214294Seric 	f = fopen("/dev/null", type);
2154081Seric 	(void) close(fileno(f));
216294Seric 	fileno(f) = fd;
217294Seric 	return (f);
218294Seric }
219294Seric /*
220294Seric **  INDEX -- Return pointer to character in string
221294Seric **
222294Seric **	For V7 compatibility.
223294Seric **
224294Seric **	Parameters:
225294Seric **		s -- a string to scan.
226294Seric **		c -- a character to look for.
227294Seric **
228294Seric **	Returns:
229294Seric **		If c is in s, returns the address of the first
230294Seric **			instance of c in s.
231294Seric **		NULL if c is not in s.
232294Seric **
233294Seric **	Side Effects:
234294Seric **		none.
235294Seric */
236294Seric 
2374437Seric char *
238294Seric index(s, c)
239294Seric 	register char *s;
240294Seric 	register char c;
241294Seric {
242294Seric 	while (*s != '\0')
243294Seric 	{
244294Seric 		if (*s++ == c)
245294Seric 			return (--s);
246294Seric 	}
247294Seric 	return (NULL);
248294Seric }
2494326Seric /*
2504326Seric **  UMASK -- fake the umask system call.
2514326Seric **
2524326Seric **	Since V6 always acts like the umask is zero, we will just
2534326Seric **	assume the same thing.
2544326Seric */
2554326Seric 
2564326Seric /*ARGSUSED*/
2574326Seric umask(nmask)
2584326Seric {
2594326Seric 	return (0);
2604326Seric }
2614326Seric 
2624326Seric 
2634326Seric /*
2644326Seric **  GETRUID -- get real user id.
2654326Seric */
2664326Seric 
2674326Seric getruid()
2684326Seric {
2694326Seric 	return (getuid() & 0377);
2704326Seric }
2714326Seric 
2724326Seric 
2734326Seric /*
2744326Seric **  GETRGID -- get real group id.
2754326Seric */
2764326Seric 
2774326Seric getrgid()
2784326Seric {
2794326Seric 	return (getgid() & 0377);
2804326Seric }
2814326Seric 
2824326Seric 
2834326Seric /*
2844326Seric **  GETEUID -- get effective user id.
2854326Seric */
2864326Seric 
2874326Seric geteuid()
2884326Seric {
2894326Seric 	return ((getuid() >> 8) & 0377);
2904326Seric }
2914326Seric 
2924326Seric 
2934326Seric /*
2944326Seric **  GETEGID -- get effective group id.
2954326Seric */
2964326Seric 
2974326Seric getegid()
2984326Seric {
2994326Seric 	return ((getgid() >> 8) & 0377);
3004326Seric }
3014326Seric 
302294Seric # endif V6
3034326Seric 
3044326Seric # ifndef V6
3054326Seric 
3064326Seric /*
3074326Seric **  GETRUID -- get real user id (V7)
3084326Seric */
3094326Seric 
3104326Seric getruid()
3114326Seric {
3129274Seric 	if (OpMode == MD_DAEMON)
3134536Seric 		return (RealUid);
3144536Seric 	else
3154536Seric 		return (getuid());
3164326Seric }
3174326Seric 
3184326Seric 
3194326Seric /*
3204326Seric **  GETRGID -- get real group id (V7).
3214326Seric */
3224326Seric 
3234326Seric getrgid()
3244326Seric {
3259274Seric 	if (OpMode == MD_DAEMON)
3264536Seric 		return (RealGid);
3274536Seric 	else
3284536Seric 		return (getgid());
3294326Seric }
3304326Seric 
3314326Seric # endif V6
3324190Seric /*
3339369Seric **  USERNAME -- return the user id of the logged in user.
3349369Seric **
3359369Seric **	Parameters:
3369369Seric **		none.
3379369Seric **
3389369Seric **	Returns:
3399369Seric **		The login name of the logged in user.
3409369Seric **
3419369Seric **	Side Effects:
3429369Seric **		none.
3439369Seric **
3449369Seric **	Notes:
3459369Seric **		The return value is statically allocated.
3469369Seric */
3479369Seric 
3489369Seric char *
3499369Seric username()
3509369Seric {
35117469Seric 	static char *myname = NULL;
3529369Seric 	extern char *getlogin();
35319904Smiriam 	register struct passwd *pw;
35419904Smiriam 	extern struct passwd *getpwuid();
3559369Seric 
35617469Seric 	/* cache the result */
35717469Seric 	if (myname == NULL)
35817469Seric 	{
35917469Seric 		myname = getlogin();
36017469Seric 		if (myname == NULL || myname[0] == '\0')
36117469Seric 		{
36217469Seric 
36317469Seric 			pw = getpwuid(getruid());
36417469Seric 			if (pw != NULL)
36517469Seric 				myname = pw->pw_name;
36617469Seric 		}
36719904Smiriam 		else
36819904Smiriam 		{
36919873Smiriam 
37019873Smiriam 			pw = getpwnam(myname);
37119904Smiriam 			if(getuid() != pw->pw_uid)
37219904Smiriam 			{
37319873Smiriam 				pw = getpwuid(getuid());
374*24943Seric 				myname = pw->pw_name;
37519873Smiriam 			}
37619873Smiriam 		}
37717469Seric 		if (myname == NULL || myname[0] == '\0')
37817469Seric 		{
37917469Seric 			syserr("Who are you?");
38017469Seric 			myname = "postmaster";
38117469Seric 		}
38217469Seric 	}
38317469Seric 
38417469Seric 	return (myname);
3859369Seric }
3869369Seric /*
3874190Seric **  TTYPATH -- Get the path of the user's tty
388294Seric **
389294Seric **	Returns the pathname of the user's tty.  Returns NULL if
390294Seric **	the user is not logged in or if s/he has write permission
391294Seric **	denied.
392294Seric **
393294Seric **	Parameters:
394294Seric **		none
395294Seric **
396294Seric **	Returns:
397294Seric **		pathname of the user's tty.
398294Seric **		NULL if not logged in or write permission denied.
399294Seric **
400294Seric **	Side Effects:
401294Seric **		none.
402294Seric **
403294Seric **	WARNING:
404294Seric **		Return value is in a local buffer.
405294Seric **
406294Seric **	Called By:
407294Seric **		savemail
408294Seric */
409294Seric 
410294Seric # include <sys/stat.h>
411294Seric 
412294Seric char *
413294Seric ttypath()
414294Seric {
415294Seric 	struct stat stbuf;
416294Seric 	register char *pathn;
417294Seric 	extern char *ttyname();
4184081Seric 	extern char *getlogin();
419294Seric 
420294Seric 	/* compute the pathname of the controlling tty */
4219369Seric 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
4229369Seric 	    (pathn = ttyname(0)) == NULL)
423294Seric 	{
424294Seric 		errno = 0;
425294Seric 		return (NULL);
426294Seric 	}
427294Seric 
428294Seric 	/* see if we have write permission */
4292967Seric 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
430294Seric 	{
431294Seric 		errno = 0;
432294Seric 		return (NULL);
433294Seric 	}
434294Seric 
435294Seric 	/* see if the user is logged in */
436294Seric 	if (getlogin() == NULL)
437294Seric 		return (NULL);
438294Seric 
439294Seric 	/* looks good */
440294Seric 	return (pathn);
441294Seric }
4422967Seric /*
4432967Seric **  CHECKCOMPAT -- check for From and To person compatible.
4442967Seric **
4452967Seric **	This routine can be supplied on a per-installation basis
4462967Seric **	to determine whether a person is allowed to send a message.
4472967Seric **	This allows restriction of certain types of internet
4482967Seric **	forwarding or registration of users.
4492967Seric **
4502967Seric **	If the hosts are found to be incompatible, an error
4512967Seric **	message should be given using "usrerr" and FALSE should
4522967Seric **	be returned.
4532967Seric **
4544288Seric **	'NoReturn' can be set to suppress the return-to-sender
4554288Seric **	function; this should be done on huge messages.
4564288Seric **
4572967Seric **	Parameters:
4582967Seric **		to -- the person being sent to.
4592967Seric **
4602967Seric **	Returns:
4612967Seric **		TRUE -- ok to send.
4622967Seric **		FALSE -- not ok.
4632967Seric **
4642967Seric **	Side Effects:
4652967Seric **		none (unless you include the usrerr stuff)
4662967Seric */
4672967Seric 
4682967Seric bool
4692967Seric checkcompat(to)
4702967Seric 	register ADDRESS *to;
4712967Seric {
47212133Seric # ifdef lint
47312133Seric 	if (to == NULL)
47412133Seric 		to++;
47512133Seric # endif lint
47610698Seric # ifdef EXAMPLE_CODE
47710698Seric 	/* this code is intended as an example only */
4784437Seric 	register STAB *s;
4794437Seric 
4804437Seric 	s = stab("arpa", ST_MAILER, ST_FIND);
4819369Seric 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
4829369Seric 	    to->q_mailer == s->s_mailer)
4834437Seric 	{
4844437Seric 		usrerr("No ARPA mail through this machine: see your system administration");
48510698Seric 		/* NoReturn = TRUE; to supress return copy */
4864437Seric 		return (FALSE);
4874437Seric 	}
48810698Seric # endif EXAMPLE_CODE
4892967Seric 	return (TRUE);
4902967Seric }
4919369Seric /*
4929369Seric **  HOLDSIGS -- arrange to hold all signals
4939369Seric **
4949369Seric **	Parameters:
4959369Seric **		none.
4969369Seric **
4979369Seric **	Returns:
4989369Seric **		none.
4999369Seric **
5009369Seric **	Side Effects:
5019369Seric **		Arranges that signals are held.
5029369Seric */
5039369Seric 
5049369Seric holdsigs()
5059369Seric {
5069369Seric }
5079369Seric /*
5089369Seric **  RLSESIGS -- arrange to release all signals
5099369Seric **
5109369Seric **	This undoes the effect of holdsigs.
5119369Seric **
5129369Seric **	Parameters:
5139369Seric **		none.
5149369Seric **
5159369Seric **	Returns:
5169369Seric **		none.
5179369Seric **
5189369Seric **	Side Effects:
5199369Seric **		Arranges that signals are released.
5209369Seric */
5219369Seric 
5229369Seric rlsesigs()
5239369Seric {
5249369Seric }
52514872Seric /*
52614872Seric **  GETLA -- get the current load average
52714872Seric **
52814881Seric **	This code stolen from la.c.
52914881Seric **
53014872Seric **	Parameters:
53114872Seric **		none.
53214872Seric **
53314872Seric **	Returns:
53414872Seric **		The current load average as an integer.
53514872Seric **
53614872Seric **	Side Effects:
53714872Seric **		none.
53814872Seric */
53914872Seric 
54014872Seric #ifdef VMUNIX
54114872Seric 
54214872Seric #include <nlist.h>
54314872Seric 
54414872Seric struct	nlist Nl[] =
54514872Seric {
54614872Seric 	{ "_avenrun" },
54714872Seric #define	X_AVENRUN	0
54814872Seric 	{ 0 },
54914872Seric };
55014872Seric 
55114872Seric getla()
55214872Seric {
55314872Seric 	static int kmem = -1;
554*24943Seric # ifdef sun
555*24943Seric 	long avenrun[3];
556*24943Seric # else
55714872Seric 	double avenrun[3];
558*24943Seric # endif
55914872Seric 
56014872Seric 	if (kmem < 0)
56114872Seric 	{
562*24943Seric 		kmem = open("/dev/kmem", 0);
56314872Seric 		if (kmem < 0)
56414872Seric 			return (-1);
56523118Seric 		(void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
56614872Seric 		nlist("/vmunix", Nl);
56714872Seric 		if (Nl[0].n_type == 0)
56814872Seric 			return (-1);
56914872Seric 	}
570*24943Seric 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) < 0 ||
57123118Seric 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
57219967Seric 	{
57319967Seric 		/* thank you Ian */
57419967Seric 		return (-1);
57519967Seric 	}
576*24943Seric # ifdef sun
577*24943Seric 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
578*24943Seric # else
57914872Seric 	return ((int) (avenrun[0] + 0.5));
580*24943Seric # endif
58114872Seric }
58214872Seric 
58314872Seric #else VMUNIX
58414872Seric 
58514872Seric getla()
58614872Seric {
58714872Seric 	return (0);
58814872Seric }
58914872Seric 
59014872Seric #endif VMUNIX
591*24943Seric /*
592*24943Seric **  SHOULDQUEUE -- should this message be queued or sent?
593*24943Seric **
594*24943Seric **	Compares the message cost to the load average to decide.
595*24943Seric **
596*24943Seric **	Parameters:
597*24943Seric **		pri -- the priority of the message in question.
598*24943Seric **
599*24943Seric **	Returns:
600*24943Seric **		TRUE -- if this message should be queued up for the
601*24943Seric **			time being.
602*24943Seric **		FALSE -- if the load is low enough to send this message.
603*24943Seric **
604*24943Seric **	Side Effects:
605*24943Seric **		none.
606*24943Seric */
607*24943Seric 
608*24943Seric bool
609*24943Seric shouldqueue(pri)
610*24943Seric 	long pri;
611*24943Seric {
612*24943Seric 	int la;
613*24943Seric 
614*24943Seric 	la = getla();
615*24943Seric 	if (la < QueueLA)
616*24943Seric 		return (FALSE);
617*24943Seric 	return (pri > (QueueFactor / (la - QueueLA + 1)));
618*24943Seric }
619*24943Seric /*
620*24943Seric **  SETPROCTITLE -- set process title for ps
621*24943Seric **
622*24943Seric **	Parameters:
623*24943Seric **		fmt -- a printf style format string.
624*24943Seric **		a, b, c -- possible parameters to fmt.
625*24943Seric **
626*24943Seric **	Returns:
627*24943Seric **		none.
628*24943Seric **
629*24943Seric **	Side Effects:
630*24943Seric **		Clobbers argv of our main procedure so ps(1) will
631*24943Seric **		display the title.
632*24943Seric */
633*24943Seric 
634*24943Seric /*VARARGS1*/
635*24943Seric setproctitle(fmt, a, b, c)
636*24943Seric 	char *fmt;
637*24943Seric {
638*24943Seric # ifdef SETPROCTITLE
639*24943Seric 	register char *p;
640*24943Seric 	extern char **Argv;
641*24943Seric 	extern char *LastArgv;
642*24943Seric 
643*24943Seric 	p = Argv[0];
644*24943Seric 
645*24943Seric 	/* make ps print "(sendmail)" */
646*24943Seric 	*p++ = '-';
647*24943Seric 
648*24943Seric 	(void) sprintf(p, fmt, a, b, c);
649*24943Seric 	p += strlen(p);
650*24943Seric 
651*24943Seric 	/* avoid confusing ps */
652*24943Seric 	while (p < LastArgv)
653*24943Seric 		*p++ = ' ';
654*24943Seric # endif SETPROCTITLE
655*24943Seric }
656