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