xref: /original-bsd/usr.sbin/sendmail/src/conf.c (revision 89e46f9f)
1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)conf.c	5.35 (Berkeley) 03/20/92";
11 #endif /* not lint */
12 
13 # include <sys/ioctl.h>
14 # include <sys/param.h>
15 # include <pwd.h>
16 # include "sendmail.h"
17 # include "pathnames.h"
18 
19 /*
20 **  CONF.C -- Sendmail Configuration Tables.
21 **
22 **	Defines the configuration of this installation.
23 **
24 **	Configuration Variables:
25 **		HdrInfo -- a table describing well-known header fields.
26 **			Each entry has the field name and some flags,
27 **			which are described in sendmail.h.
28 **
29 **	Notes:
30 **		I have tried to put almost all the reasonable
31 **		configuration information into the configuration
32 **		file read at runtime.  My intent is that anything
33 **		here is a function of the version of UNIX you
34 **		are running, or is really static -- for example
35 **		the headers are a superset of widely used
36 **		protocols.  If you find yourself playing with
37 **		this file too much, you may be making a mistake!
38 */
39 
40 
41 
42 
43 /*
44 **  Header info table
45 **	Final (null) entry contains the flags used for any other field.
46 **
47 **	Not all of these are actually handled specially by sendmail
48 **	at this time.  They are included as placeholders, to let
49 **	you know that "someday" I intend to have sendmail do
50 **	something with them.
51 */
52 
53 struct hdrinfo	HdrInfo[] =
54 {
55 		/* originator fields, most to least significant  */
56 	"resent-sender",	H_FROM|H_RESENT,
57 	"resent-from",		H_FROM|H_RESENT,
58 	"resent-reply-to",	H_FROM|H_RESENT,
59 	"sender",		H_FROM,
60 	"from",			H_FROM,
61 	"reply-to",		H_FROM,
62 	"full-name",		H_ACHECK,
63 	"return-receipt-to",	H_FROM,
64 	"errors-to",		H_FROM,
65 		/* destination fields */
66 	"to",			H_RCPT,
67 	"resent-to",		H_RCPT|H_RESENT,
68 	"cc",			H_RCPT,
69 	"resent-cc",		H_RCPT|H_RESENT,
70 	"bcc",			H_RCPT|H_ACHECK,
71 	"resent-bcc",		H_RCPT|H_ACHECK|H_RESENT,
72 		/* message identification and control */
73 	"message-id",		0,
74 	"resent-message-id",	H_RESENT,
75 	"message",		H_EOH,
76 	"text",			H_EOH,
77 		/* date fields */
78 	"date",			0,
79 	"resent-date",		H_RESENT,
80 		/* trace fields */
81 	"received",		H_TRACE|H_FORCE,
82 	"via",			H_TRACE|H_FORCE,
83 	"mail-from",		H_TRACE|H_FORCE,
84 
85 	NULL,			0,
86 };
87 
88 
89 /*
90 **  ARPANET error message numbers.
91 */
92 
93 char	Arpa_Info[] =		"050";	/* arbitrary info */
94 char	Arpa_TSyserr[] =	"451";	/* some (transient) system error */
95 char	Arpa_PSyserr[] =	"554";	/* some (permanent) system error */
96 char	Arpa_Usrerr[] =		"554";	/* some (fatal) user error */
97 
98 
99 
100 /*
101 **  Location of system files/databases/etc.
102 */
103 
104 char	*ConfFile =	_PATH_SENDMAILCF;	/* runtime configuration */
105 char	*FreezeFile =	_PATH_SENDMAILFC;	/* frozen version of above */
106 
107 
108 
109 /*
110 **  Miscellaneous stuff.
111 */
112 
113 int	DtableSize =	50;		/* max open files; reset in 4.2bsd */
114 /*
115 **  SETDEFAULTS -- set default values
116 **
117 **	Because of the way freezing is done, these must be initialized
118 **	using direct code.
119 **
120 **	Parameters:
121 **		none.
122 **
123 **	Returns:
124 **		none.
125 **
126 **	Side Effects:
127 **		Initializes a bunch of global variables to their
128 **		default values.
129 */
130 
131 setdefaults()
132 {
133 	QueueLA = 8;
134 	QueueFactor = 10000;
135 	RefuseLA = 12;
136 	SpaceSub = ' ';
137 	WkRecipFact = 1000;
138 	WkClassFact = 1800;
139 	WkTimeFact = 9000;
140 	FileMode = 0644;
141 	DefUid = 1;
142 	DefGid = 1;
143 	CheckpointInterval = 10;
144 	MaxHopCount = MAXHOP;
145 	SendMode = SM_FORK;
146 	ErrorMode = EM_PRINT;
147 	EightBit = FALSE;
148 	setdefuser();
149 }
150 
151 
152 /*
153 **  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
154 */
155 
156 setdefuser()
157 {
158 	struct passwd *defpwent;
159 
160 	if (DefUser != NULL)
161 		free(DefUser);
162 	if ((defpwent = getpwuid(DefUid)) != NULL)
163 		DefUser = newstr(defpwent->pw_name);
164 	else
165 		DefUser = newstr("nobody");
166 }
167 
168 
169 /*
170 **  GETRUID -- get real user id (V7)
171 */
172 
173 getruid()
174 {
175 	if (OpMode == MD_DAEMON)
176 		return (RealUid);
177 	else
178 		return (getuid());
179 }
180 
181 
182 /*
183 **  GETRGID -- get real group id (V7).
184 */
185 
186 getrgid()
187 {
188 	if (OpMode == MD_DAEMON)
189 		return (RealGid);
190 	else
191 		return (getgid());
192 }
193 
194 /*
195 **  USERNAME -- return the user id of the logged in user.
196 **
197 **	Parameters:
198 **		none.
199 **
200 **	Returns:
201 **		The login name of the logged in user.
202 **
203 **	Side Effects:
204 **		none.
205 **
206 **	Notes:
207 **		The return value is statically allocated.
208 */
209 
210 char *
211 username()
212 {
213 	static char *myname = NULL;
214 	extern char *getlogin();
215 	register struct passwd *pw;
216 
217 	/* cache the result */
218 	if (myname == NULL)
219 	{
220 		myname = getlogin();
221 		if (myname == NULL || myname[0] == '\0')
222 		{
223 
224 			pw = getpwuid(getruid());
225 			if (pw != NULL)
226 				myname = newstr(pw->pw_name);
227 		}
228 		else
229 		{
230 
231 			myname = newstr(myname);
232 			if ((pw = getpwnam(myname)) == NULL ||
233 			      getuid() != pw->pw_uid)
234 			{
235 				pw = getpwuid(getuid());
236 				if (pw != NULL)
237 					myname = newstr(pw->pw_name);
238 			}
239 		}
240 		if (myname == NULL || myname[0] == '\0')
241 		{
242 			syserr("Who are you?");
243 			myname = "postmaster";
244 		}
245 	}
246 
247 	return (myname);
248 }
249 /*
250 **  TTYPATH -- Get the path of the user's tty
251 **
252 **	Returns the pathname of the user's tty.  Returns NULL if
253 **	the user is not logged in or if s/he has write permission
254 **	denied.
255 **
256 **	Parameters:
257 **		none
258 **
259 **	Returns:
260 **		pathname of the user's tty.
261 **		NULL if not logged in or write permission denied.
262 **
263 **	Side Effects:
264 **		none.
265 **
266 **	WARNING:
267 **		Return value is in a local buffer.
268 **
269 **	Called By:
270 **		savemail
271 */
272 
273 # include <sys/stat.h>
274 
275 char *
276 ttypath()
277 {
278 	struct stat stbuf;
279 	register char *pathn;
280 	extern char *ttyname();
281 	extern char *getlogin();
282 
283 	/* compute the pathname of the controlling tty */
284 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
285 	    (pathn = ttyname(0)) == NULL)
286 	{
287 		errno = 0;
288 		return (NULL);
289 	}
290 
291 	/* see if we have write permission */
292 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
293 	{
294 		errno = 0;
295 		return (NULL);
296 	}
297 
298 	/* see if the user is logged in */
299 	if (getlogin() == NULL)
300 		return (NULL);
301 
302 	/* looks good */
303 	return (pathn);
304 }
305 /*
306 **  CHECKCOMPAT -- check for From and To person compatible.
307 **
308 **	This routine can be supplied on a per-installation basis
309 **	to determine whether a person is allowed to send a message.
310 **	This allows restriction of certain types of internet
311 **	forwarding or registration of users.
312 **
313 **	If the hosts are found to be incompatible, an error
314 **	message should be given using "usrerr" and FALSE should
315 **	be returned.
316 **
317 **	'NoReturn' can be set to suppress the return-to-sender
318 **	function; this should be done on huge messages.
319 **
320 **	Parameters:
321 **		to -- the person being sent to.
322 **
323 **	Returns:
324 **		TRUE -- ok to send.
325 **		FALSE -- not ok.
326 **
327 **	Side Effects:
328 **		none (unless you include the usrerr stuff)
329 */
330 
331 bool
332 checkcompat(to)
333 	register ADDRESS *to;
334 {
335 # ifdef lint
336 	if (to == NULL)
337 		to++;
338 # endif lint
339 # ifdef EXAMPLE_CODE
340 	/* this code is intended as an example only */
341 	register STAB *s;
342 
343 	s = stab("arpa", ST_MAILER, ST_FIND);
344 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
345 	    to->q_mailer == s->s_mailer)
346 	{
347 		usrerr("No ARPA mail through this machine: see your system administration");
348 		/* NoReturn = TRUE; to supress return copy */
349 		return (FALSE);
350 	}
351 # endif EXAMPLE_CODE
352 	return (TRUE);
353 }
354 /*
355 **  HOLDSIGS -- arrange to hold all signals
356 **
357 **	Parameters:
358 **		none.
359 **
360 **	Returns:
361 **		none.
362 **
363 **	Side Effects:
364 **		Arranges that signals are held.
365 */
366 
367 holdsigs()
368 {
369 }
370 /*
371 **  RLSESIGS -- arrange to release all signals
372 **
373 **	This undoes the effect of holdsigs.
374 **
375 **	Parameters:
376 **		none.
377 **
378 **	Returns:
379 **		none.
380 **
381 **	Side Effects:
382 **		Arranges that signals are released.
383 */
384 
385 rlsesigs()
386 {
387 }
388 /*
389 **  GETLA -- get the current load average
390 **
391 **	This code stolen from la.c.
392 **
393 **	Parameters:
394 **		none.
395 **
396 **	Returns:
397 **		The current load average as an integer.
398 **
399 **	Side Effects:
400 **		none.
401 */
402 
403 /* try to guess what style of load average we have */
404 #define LA_ZERO		1	/* always return load average as zero */
405 #define LA_INT		2	/* read kmem for avenrun; interpret as int */
406 #define LA_FLOAT	3	/* read kmem for avenrun; interpret as float */
407 #define LA_SUBR		4	/* call getloadavg */
408 
409 #ifndef LA_TYPE
410 #  if defined(sun)
411 #    define LA_TYPE		LA_INT
412 #  endif
413 #  if defined(mips)
414      /* Ultrix or RISC/os */
415 #    define LA_TYPE		LA_INT
416 #    define LA_AVENRUN		"avenrun"
417 #  endif
418 #  if defined(hpux)
419 #    define LA_TYPE		LA_FLOAT
420 #  endif
421 #  if defined(BSD)
422 #    define LA_TYPE		LA_SUBR
423 #  endif
424 
425 #  ifndef LA_TYPE
426 #    define LA_TYPE		LA_ZERO
427 #  endif
428 #endif
429 
430 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT)
431 
432 #include <nlist.h>
433 #include <fcntl.h>
434 
435 #ifndef LA_AVENRUN
436 #define LA_AVENRUN	"_avenrun"
437 #endif
438 
439 /* _PATH_UNIX should be defined in <paths.h> */
440 #ifndef _PATH_UNIX
441 #  if defined(hpux)
442 #    define _PATH_UNIX		"/hp-ux"
443 #  endif
444 #  if defined(mips) && !defined(ultrix)
445      /* powerful RISC/os */
446 #    define _PATH_UNIX		"/unix"
447 #  endif
448 #  ifndef _PATH_UNIX
449 #    define _PATH_UNIX		"/vmunix"
450 #  endif
451 #endif
452 
453 struct	nlist Nl[] =
454 {
455 	{ LA_AVENRUN },
456 #define	X_AVENRUN	0
457 	{ 0 },
458 };
459 
460 #if (LA_TYPE == LA_INT) && !defined(FSHIFT)
461 #  define FSHIFT	8
462 #  define FSCALE	(1 << FSHIFT)
463 #endif
464 
465 getla()
466 {
467 	static int kmem = -1;
468 #if LA_TYPE == LA_INT
469 	long avenrun[3];
470 #else
471 	double avenrun[3];
472 #endif
473 	extern off_t lseek();
474 
475 	if (kmem < 0)
476 	{
477 		kmem = open("/dev/kmem", 0, 0);
478 		if (kmem < 0)
479 			return (-1);
480 		(void) fcntl(kmem, F_SETFD, 1);
481 		nlist(_PATH_UNIX, Nl);
482 		if (Nl[0].n_type == 0)
483 			return (-1);
484 	}
485 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
486 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
487 	{
488 		/* thank you Ian */
489 		return (-1);
490 	}
491 #if LA_TYPE == LA_INT
492 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
493 #else
494 	return ((int) (avenrun[0] + 0.5));
495 #endif
496 }
497 
498 #else
499 #if LA_TYPE == LA_SUBR
500 
501 getla()
502 {
503 	double avenrun[3];
504 
505 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
506 		return (-1);
507 	return ((int) (avenrun[0] + 0.5));
508 }
509 
510 #else
511 
512 getla()
513 {
514 	return (0);
515 }
516 
517 #endif
518 #endif
519 /*
520 **  SHOULDQUEUE -- should this message be queued or sent?
521 **
522 **	Compares the message cost to the load average to decide.
523 **
524 **	Parameters:
525 **		pri -- the priority of the message in question.
526 **
527 **	Returns:
528 **		TRUE -- if this message should be queued up for the
529 **			time being.
530 **		FALSE -- if the load is low enough to send this message.
531 **
532 **	Side Effects:
533 **		none.
534 */
535 
536 bool
537 shouldqueue(pri)
538 	long pri;
539 {
540 	if (CurrentLA < QueueLA)
541 		return (FALSE);
542 	return (pri > (QueueFactor / (CurrentLA - QueueLA + 1)));
543 }
544 /*
545 **  REFUSECONNECTIONS -- decide if connections should be refused
546 **
547 **	Parameters:
548 **		none.
549 **
550 **	Returns:
551 **		TRUE if incoming SMTP connections should be refused
552 **			(for now).
553 **		FALSE if we should accept new work.
554 **
555 **	Side Effects:
556 **		none.
557 */
558 
559 bool
560 refuseconnections()
561 {
562 	/* this is probably too simplistic */
563 	return (CurrentLA > RefuseLA);
564 }
565 /*
566 **  SETPROCTITLE -- set process title for ps
567 **
568 **	Parameters:
569 **		fmt -- a printf style format string.
570 **		a, b, c -- possible parameters to fmt.
571 **
572 **	Returns:
573 **		none.
574 **
575 **	Side Effects:
576 **		Clobbers argv of our main procedure so ps(1) will
577 **		display the title.
578 */
579 
580 /*VARARGS1*/
581 setproctitle(fmt, a, b, c)
582 	char *fmt;
583 {
584 # ifdef SETPROCTITLE
585 	register char *p;
586 	register int i;
587 	extern char **Argv;
588 	extern char *LastArgv;
589 	char buf[MAXLINE];
590 
591 	(void) sprintf(buf, fmt, a, b, c);
592 
593 	/* make ps print "(sendmail)" */
594 	p = Argv[0];
595 	*p++ = '-';
596 
597 	i = strlen(buf);
598 	if (i > LastArgv - p - 2)
599 	{
600 		i = LastArgv - p - 2;
601 		buf[i] = '\0';
602 	}
603 	(void) strcpy(p, buf);
604 	p += i;
605 	while (p < LastArgv)
606 		*p++ = ' ';
607 # endif SETPROCTITLE
608 }
609 /*
610 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
611 **
612 **	Parameters:
613 **		none.
614 **
615 **	Returns:
616 **		none.
617 **
618 **	Side Effects:
619 **		Picks up extant zombies.
620 */
621 
622 # include <sys/wait.h>
623 
624 void
625 reapchild()
626 {
627 # ifdef WNOHANG
628 	union wait status;
629 
630 	while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
631 		continue;
632 # else WNOHANG
633 	auto int status;
634 
635 	while (wait((int *)&status) > 0)
636 		continue;
637 # endif WNOHANG
638 }
639