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