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