xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 52105)
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.32 (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 	setdefuser();
151 }
152 
153 
154 /*
155 **  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
156 */
157 
158 setdefuser()
159 {
160 	struct passwd *defpwent;
161 
162 	if (DefUser != NULL)
163 		free(DefUser);
164 	if ((defpwent = getpwuid(DefUid)) != NULL)
165 		DefUser = newstr(defpwent->pw_name);
166 	else
167 		DefUser = newstr("nobody");
168 }
169 
170 
171 /*
172 **  GETRUID -- get real user id (V7)
173 */
174 
175 getruid()
176 {
177 	if (OpMode == MD_DAEMON)
178 		return (RealUid);
179 	else
180 		return (getuid());
181 }
182 
183 
184 /*
185 **  GETRGID -- get real group id (V7).
186 */
187 
188 getrgid()
189 {
190 	if (OpMode == MD_DAEMON)
191 		return (RealGid);
192 	else
193 		return (getgid());
194 }
195 
196 /*
197 **  USERNAME -- return the user id of the logged in user.
198 **
199 **	Parameters:
200 **		none.
201 **
202 **	Returns:
203 **		The login name of the logged in user.
204 **
205 **	Side Effects:
206 **		none.
207 **
208 **	Notes:
209 **		The return value is statically allocated.
210 */
211 
212 char *
213 username()
214 {
215 	static char *myname = NULL;
216 	extern char *getlogin();
217 	register struct passwd *pw;
218 
219 	/* cache the result */
220 	if (myname == NULL)
221 	{
222 		myname = getlogin();
223 		if (myname == NULL || myname[0] == '\0')
224 		{
225 
226 			pw = getpwuid(getruid());
227 			if (pw != NULL)
228 				myname = newstr(pw->pw_name);
229 		}
230 		else
231 		{
232 
233 			myname = newstr(myname);
234 			if ((pw = getpwnam(myname)) == NULL ||
235 			      getuid() != pw->pw_uid)
236 			{
237 				pw = getpwuid(getuid());
238 				if (pw != NULL)
239 					myname = newstr(pw->pw_name);
240 			}
241 		}
242 		if (myname == NULL || myname[0] == '\0')
243 		{
244 			syserr("Who are you?");
245 			myname = "postmaster";
246 		}
247 	}
248 
249 	return (myname);
250 }
251 /*
252 **  TTYPATH -- Get the path of the user's tty
253 **
254 **	Returns the pathname of the user's tty.  Returns NULL if
255 **	the user is not logged in or if s/he has write permission
256 **	denied.
257 **
258 **	Parameters:
259 **		none
260 **
261 **	Returns:
262 **		pathname of the user's tty.
263 **		NULL if not logged in or write permission denied.
264 **
265 **	Side Effects:
266 **		none.
267 **
268 **	WARNING:
269 **		Return value is in a local buffer.
270 **
271 **	Called By:
272 **		savemail
273 */
274 
275 # include <sys/stat.h>
276 
277 char *
278 ttypath()
279 {
280 	struct stat stbuf;
281 	register char *pathn;
282 	extern char *ttyname();
283 	extern char *getlogin();
284 
285 	/* compute the pathname of the controlling tty */
286 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
287 	    (pathn = ttyname(0)) == NULL)
288 	{
289 		errno = 0;
290 		return (NULL);
291 	}
292 
293 	/* see if we have write permission */
294 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
295 	{
296 		errno = 0;
297 		return (NULL);
298 	}
299 
300 	/* see if the user is logged in */
301 	if (getlogin() == NULL)
302 		return (NULL);
303 
304 	/* looks good */
305 	return (pathn);
306 }
307 /*
308 **  CHECKCOMPAT -- check for From and To person compatible.
309 **
310 **	This routine can be supplied on a per-installation basis
311 **	to determine whether a person is allowed to send a message.
312 **	This allows restriction of certain types of internet
313 **	forwarding or registration of users.
314 **
315 **	If the hosts are found to be incompatible, an error
316 **	message should be given using "usrerr" and FALSE should
317 **	be returned.
318 **
319 **	'NoReturn' can be set to suppress the return-to-sender
320 **	function; this should be done on huge messages.
321 **
322 **	Parameters:
323 **		to -- the person being sent to.
324 **
325 **	Returns:
326 **		TRUE -- ok to send.
327 **		FALSE -- not ok.
328 **
329 **	Side Effects:
330 **		none (unless you include the usrerr stuff)
331 */
332 
333 bool
334 checkcompat(to)
335 	register ADDRESS *to;
336 {
337 # ifdef lint
338 	if (to == NULL)
339 		to++;
340 # endif lint
341 # ifdef EXAMPLE_CODE
342 	/* this code is intended as an example only */
343 	register STAB *s;
344 
345 	s = stab("arpa", ST_MAILER, ST_FIND);
346 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
347 	    to->q_mailer == s->s_mailer)
348 	{
349 		usrerr("No ARPA mail through this machine: see your system administration");
350 		/* NoReturn = TRUE; to supress return copy */
351 		return (FALSE);
352 	}
353 # endif EXAMPLE_CODE
354 	return (TRUE);
355 }
356 /*
357 **  HOLDSIGS -- arrange to hold all signals
358 **
359 **	Parameters:
360 **		none.
361 **
362 **	Returns:
363 **		none.
364 **
365 **	Side Effects:
366 **		Arranges that signals are held.
367 */
368 
369 holdsigs()
370 {
371 }
372 /*
373 **  RLSESIGS -- arrange to release all signals
374 **
375 **	This undoes the effect of holdsigs.
376 **
377 **	Parameters:
378 **		none.
379 **
380 **	Returns:
381 **		none.
382 **
383 **	Side Effects:
384 **		Arranges that signals are released.
385 */
386 
387 rlsesigs()
388 {
389 }
390 /*
391 **  GETLA -- get the current load average
392 **
393 **	This code stolen from la.c.
394 **
395 **	Parameters:
396 **		none.
397 **
398 **	Returns:
399 **		The current load average as an integer.
400 **
401 **	Side Effects:
402 **		none.
403 */
404 
405 /* try to guess what style of load average we have */
406 #define LA_ZERO		1	/* always return load average as zero */
407 #define LA_INT		2	/* read kmem for avenrun; interpret as int */
408 #define LA_FLOAT	3	/* read kmem for avenrun; interpret as float */
409 #define LA_SUBR		4	/* call getloadavg */
410 
411 #ifndef LA_TYPE
412 #  if defined(sun)
413 #    define LA_TYPE		LA_INT
414 #  endif
415 #  if defined(mips)
416      /* Ultrix or RISC/os */
417 #    define LA_TYPE		LA_INT
418 #    define LA_AVENRUN		"avenrun"
419 #  endif
420 #  if defined(hpux)
421 #    define LA_TYPE		LA_FLOAT
422 #  endif
423 #  if defined(BSD)
424 #    define LA_TYPE		LA_SUBR
425 #  endif
426 
427 #  ifndef LA_TYPE
428 #    define LA_TYPE		LA_ZERO
429 #  endif
430 #endif
431 
432 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT)
433 
434 #include <nlist.h>
435 #include <fcntl.h>
436 
437 #ifndef LA_AVENRUN
438 #define LA_AVENRUN	"_avenrun"
439 #endif
440 
441 /* _PATH_UNIX should be defined in <paths.h> */
442 #ifndef _PATH_UNIX
443 #  if defined(hpux)
444 #    define _PATH_UNIX		"/hp-ux"
445 #  endif
446 #  if defined(mips) && !defined(ultrix)
447      /* powerful RISC/os */
448 #    define _PATH_UNIX		"/unix"
449 #  endif
450 #  ifndef _PATH_UNIX
451 #    define _PATH_UNIX		"/vmunix"
452 #  endif
453 #endif
454 
455 struct	nlist Nl[] =
456 {
457 	{ LA_AVENRUN },
458 #define	X_AVENRUN	0
459 	{ 0 },
460 };
461 
462 #if (LA_TYPE == LA_INT) && !defined(FSHIFT)
463 #  define FSHIFT	8
464 #  define FSCALE	(1 << FSHIFT)
465 #endif
466 
467 getla()
468 {
469 	static int kmem = -1;
470 #if LA_TYPE == LA_INT
471 	long avenrun[3];
472 #else
473 	double avenrun[3];
474 #endif
475 	extern off_t lseek();
476 
477 	if (kmem < 0)
478 	{
479 		kmem = open("/dev/kmem", 0, 0);
480 		if (kmem < 0)
481 			return (-1);
482 		(void) fcntl(kmem, F_SETFD, 1);
483 		nlist(_PATH_UNIX, Nl);
484 		if (Nl[0].n_type == 0)
485 			return (-1);
486 	}
487 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
488 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
489 	{
490 		/* thank you Ian */
491 		return (-1);
492 	}
493 #if LA_TYPE == LA_INT
494 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
495 #else
496 	return ((int) (avenrun[0] + 0.5));
497 #endif
498 }
499 
500 #else
501 #if LA_TYPE == LA_SUBR
502 
503 getla()
504 {
505 	double avenrun[3];
506 
507 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
508 		return (-1);
509 	return ((int) (avenrun[0] + 0.5));
510 }
511 
512 #else
513 
514 getla()
515 {
516 	return (0);
517 }
518 
519 #endif
520 #endif
521 /*
522 **  SHOULDQUEUE -- should this message be queued or sent?
523 **
524 **	Compares the message cost to the load average to decide.
525 **
526 **	Parameters:
527 **		pri -- the priority of the message in question.
528 **
529 **	Returns:
530 **		TRUE -- if this message should be queued up for the
531 **			time being.
532 **		FALSE -- if the load is low enough to send this message.
533 **
534 **	Side Effects:
535 **		none.
536 */
537 
538 bool
539 shouldqueue(pri)
540 	long pri;
541 {
542 	if (CurrentLA < QueueLA)
543 		return (FALSE);
544 	return (pri > (QueueFactor / (CurrentLA - QueueLA + 1)));
545 }
546 /*
547 **  SETPROCTITLE -- set process title for ps
548 **
549 **	Parameters:
550 **		fmt -- a printf style format string.
551 **		a, b, c -- possible parameters to fmt.
552 **
553 **	Returns:
554 **		none.
555 **
556 **	Side Effects:
557 **		Clobbers argv of our main procedure so ps(1) will
558 **		display the title.
559 */
560 
561 /*VARARGS1*/
562 setproctitle(fmt, a, b, c)
563 	char *fmt;
564 {
565 # ifdef SETPROCTITLE
566 	register char *p;
567 	register int i;
568 	extern char **Argv;
569 	extern char *LastArgv;
570 	char buf[MAXLINE];
571 
572 	(void) sprintf(buf, fmt, a, b, c);
573 
574 	/* make ps print "(sendmail)" */
575 	p = Argv[0];
576 	*p++ = '-';
577 
578 	i = strlen(buf);
579 	if (i > LastArgv - p - 2)
580 	{
581 		i = LastArgv - p - 2;
582 		buf[i] = '\0';
583 	}
584 	(void) strcpy(p, buf);
585 	p += i;
586 	while (p < LastArgv)
587 		*p++ = ' ';
588 # endif SETPROCTITLE
589 }
590 /*
591 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
592 **
593 **	Parameters:
594 **		none.
595 **
596 **	Returns:
597 **		none.
598 **
599 **	Side Effects:
600 **		Picks up extant zombies.
601 */
602 
603 # ifdef VMUNIX
604 # include <sys/wait.h>
605 # endif VMUNIX
606 
607 void
608 reapchild()
609 {
610 # ifdef WNOHANG
611 	union wait status;
612 
613 	while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
614 		continue;
615 # else WNOHANG
616 	auto int status;
617 
618 	while (wait((int *)&status) > 0)
619 		continue;
620 # endif WNOHANG
621 }
622