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